Skip to content

Commit aca2703

Browse files
nikswamyCopilot
andcommitted
Add fstarmcp skill and MCP server config for Copilot CLI
Add two things for integrating fstar-mcp with Copilot CLI: 1. .copilot/mcp-config.json - Registers fstar-mcp as an HTTP MCP server on localhost:3001 so Copilot CLI auto-connects to it. 2. .github/skills/fstarmcp/SKILL.md - Skill documentation covering: - Server startup and MCP registration - API protocol (JSON-RPC 2.0 over HTTP) - Session lifecycle: create_session, typecheck_buffer, close_session - All available tools: lookup_symbol, get_proof_context, etc. - HaclPulse-specific configuration (include dirs, options) - Tips for incremental workflow, Pulse support 3. .copilot/.gitignore - Excludes user-specific files (logs, config) while keeping mcp-config.json in version control. Tested end-to-end: session creation, error detection, incremental re-typecheck, symbol lookup all work correctly with the server. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 7c23ae8 commit aca2703

3 files changed

Lines changed: 169 additions & 0 deletions

File tree

.copilot/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Exclude everything except mcp-config.json
2+
logs/
3+
config.json
4+
session-state/

.copilot/mcp-config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"mcpServers": {
3+
"fstar-mcp": {
4+
"type": "http",
5+
"url": "http://localhost:3001/"
6+
}
7+
}
8+
}

.github/skills/fstarmcp/SKILL.md

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
---
2+
name: fstarmcp
3+
description: Use the F* MCP server for interactive, incremental typechecking of F* and Pulse code
4+
---
5+
6+
## Overview
7+
8+
The F* MCP server (`fstar-mcp`) provides an HTTP API wrapping F*'s `--ide` protocol.
9+
It enables **incremental typechecking**: create a session once, then re-typecheck modified
10+
code without restarting F* or reloading dependencies. This dramatically speeds up iterative
11+
proof development.
12+
13+
Binary location: `../fstar-mcp/target/release/fstar-mcp` (relative to the FStar repo root).
14+
15+
## MCP Registration
16+
17+
The server is registered in `.copilot/mcp-config.json` at the repo root as an `http` type
18+
server on `http://localhost:3001/`. Copilot CLI will auto-connect when the server is running.
19+
20+
## Starting the Server
21+
22+
The server must be started before Copilot CLI can use it:
23+
24+
```bash
25+
# Start on port 3001 (matches mcp-config.json)
26+
FSTAR_MCP_PORT=3001 ../fstar-mcp/target/release/fstar-mcp &
27+
28+
# With debug logging
29+
RUST_LOG=fstar_mcp=debug FSTAR_MCP_PORT=3001 ../fstar-mcp/target/release/fstar-mcp &
30+
```
31+
32+
The server runs on `http://127.0.0.1:3001`. All API calls are JSON-RPC 2.0 POST requests to `/`.
33+
34+
## API Protocol
35+
36+
All requests use JSON-RPC 2.0 over HTTP POST to the root endpoint `/`:
37+
38+
```bash
39+
curl -s -X POST http://localhost:3001/ \
40+
-H 'Content-Type: application/json' \
41+
-H 'Accept: application/json' \
42+
-d '{"jsonrpc": "2.0", "method": "tools/call", "id": 1, "params": {"name": "TOOL_NAME", "arguments": {...}}}'
43+
```
44+
45+
Responses contain `result.content[0].text` with a JSON string that must be parsed again.
46+
47+
## Workflow
48+
49+
### 1. Create a Session
50+
51+
```bash
52+
curl -s -X POST http://localhost:3001/ \
53+
-H 'Content-Type: application/json' \
54+
-d '{"jsonrpc":"2.0","method":"tools/call","id":1,"params":{"name":"create_session","arguments":{
55+
"file_path": "/path/to/Module.fst",
56+
"cwd": "/project/root",
57+
"include_dirs": ["/path/to/lib", "/path/to/specs"],
58+
"options": ["--cache_dir", "/path/to/obj", "--already_cached", "Prims FStar"]
59+
}}}'
60+
```
61+
62+
**Parameters:**
63+
- `file_path` (string, optional): Path to the F* file. Must exist on disk. If omitted, creates a temp file.
64+
- `cwd` (string, optional): Working directory. Defaults to file's directory.
65+
- `include_dirs` (string[], optional): Directories for `--include`.
66+
- `options` (string[], optional): Extra F* CLI options.
67+
68+
**Returns:** `session_id`, `status` ("ok"/"error"), `diagnostics[]`, `fragments[]`
69+
70+
The initial `create_session` typechecks the file's current contents on disk. The returned
71+
`session_id` is used for all subsequent operations.
72+
73+
### 2. Typecheck Modified Code
74+
75+
```bash
76+
curl -s -X POST http://localhost:3001/ \
77+
-d '{"jsonrpc":"2.0","method":"tools/call","id":2,"params":{"name":"typecheck_buffer","arguments":{
78+
"session_id": "UUID",
79+
"code": "module Foo\nlet x = 42",
80+
"kind": "full"
81+
}}}'
82+
```
83+
84+
**Parameters:**
85+
- `session_id` (string, required): From `create_session`.
86+
- `code` (string, required): Full module source code. Must start with matching `module` declaration.
87+
- `lax` (boolean, optional): Shortcut for `kind: "lax"`.
88+
- `kind` (string, optional): `"full"` (default), `"lax"`, `"cache"`, `"reload-deps"`, `"verify-to-position"`, `"lax-to-position"`.
89+
- `to_line` / `to_column` (integer, optional): For position-based kinds.
90+
91+
**Returns:** `status`, `diagnostics[]`, `fragments[]`
92+
93+
Each fragment has `start_line`, `end_line`, `start_column`, `end_column`, and `status` ("ok"/"failed").
94+
95+
### 3. Look Up Symbols
96+
97+
```bash
98+
curl -s -X POST http://localhost:3001/ \
99+
-d '{"jsonrpc":"2.0","method":"tools/call","id":3,"params":{"name":"lookup_symbol","arguments":{
100+
"session_id": "UUID",
101+
"file_path": "/path/to/Module.fst",
102+
"line": 10, "column": 5,
103+
"symbol": "my_function"
104+
}}}'
105+
```
106+
107+
**Returns:** `kind` ("symbol"/"module"/"not_found"), `name`, `type_info`, `defined_at`.
108+
109+
### 4. Other Tools
110+
111+
- **`list_sessions`**: List all active sessions with their file paths.
112+
- **`restart_solver`**: Restart Z3 for a session (useful when solver gets stuck).
113+
- **`get_proof_context`**: Get proof obligations from tactic-based proofs.
114+
- **`update_buffer`**: Add/update files in F*'s virtual file system (vfs-add) for dependency resolution.
115+
- **`close_session`**: Clean up a session.
116+
117+
## HaclPulse Configuration
118+
119+
For verifying HaclPulse code, use these include dirs and options:
120+
121+
```json
122+
{
123+
"file_path": "/path/to/HaclPulse/code/sha3/Module.fst",
124+
"cwd": "/path/to/HaclPulse",
125+
"include_dirs": [
126+
"lib", "specs",
127+
"code/sha3", "code/chacha20", "code/salsa20", "code/sha2",
128+
"code/blake2", "code/curve25519", "code/poly1305",
129+
"obj",
130+
"../pulse/out/lib/pulse", "../pulse/out/lib/pulse/lib",
131+
"../karamel/krmllib", "../karamel/krmllib/obj"
132+
],
133+
"options": [
134+
"--cache_dir", "obj",
135+
"--already_cached", "Prims FStar LowStar C Spec.Loops TestLib WasmSupport PulseCore Pulse.Lib Pulse.Class Pulse.Main",
136+
"--ext", "pulse:rvalues",
137+
"--ext", "fly_deps",
138+
"--ext", "optimize_let_vc",
139+
"--warn_error", "@240+241@247-272-274-288@319@328@331@332@337"
140+
]
141+
}
142+
```
143+
144+
## Tips
145+
146+
- **Incremental workflow**: Create session once (slow, loads deps), then `typecheck_buffer`
147+
repeatedly (fast, only re-checks changed fragments).
148+
- **Module name must match file path**: The `module` declaration in `code` must match the
149+
file name from `create_session` (e.g., file `Spec.Poly1305.fst``module Spec.Poly1305`).
150+
- **Pulse files**: No special configuration beyond including pulse dirs. The `#lang-pulse`
151+
directive in the file is handled automatically.
152+
- **Lax mode**: Use `"lax": true` for fast syntax/type checking without SMT verification.
153+
- **Position-based verification**: Use `"kind": "verify-to-position"` with `to_line` to verify
154+
only up to a specific point — useful for large files where you're working on one function.
155+
- **Symbol lookup**: Works after a successful typecheck. Useful for finding types and
156+
definition locations of functions you need to call.
157+
- **Session replacement**: Creating a new session with the same `file_path` replaces the old one.

0 commit comments

Comments
 (0)