Skip to content

Commit 5254f1c

Browse files
committed
Merge branch 'mcp-upgrade-notes'
2 parents 9f0bfec + 46c0d45 commit 5254f1c

File tree

11 files changed

+744
-106
lines changed

11 files changed

+744
-106
lines changed

.well-known/mcp.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"$schema": "https://modelcontextprotocol.io/schemas/mcp.json",
3+
"mcpServers": {
4+
"code-index": {
5+
"command": "uv",
6+
"args": [
7+
"run",
8+
"code-index-mcp"
9+
],
10+
"transport": {
11+
"type": "stdio"
12+
},
13+
"metadata": {
14+
"name": "Code Index MCP",
15+
"description": "Local code-aware MCP server with project indexing, search, and file tools.",
16+
"homepage": "https://github.com/johnhuang316/code-index-mcp",
17+
"capabilities": [
18+
"code-search",
19+
"symbol-indexing",
20+
"file-system"
21+
]
22+
}
23+
}
24+
},
25+
"llmfeed_extension": {
26+
"path": ".well-known/mcp.llmfeed.json"
27+
}
28+
}

.well-known/mcp.llmfeed.json

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"$schema": "https://modelcontextprotocol.io/schemas/mcp-llmfeed.json",
3+
"feed_type": "mcp_server_list",
4+
"servers": [
5+
{
6+
"id": "code-index",
7+
"name": "Code Index MCP",
8+
"description": "Exposes project-aware indexing, search, and file utilities for LLM agents via MCP transports.",
9+
"version": "2.8.1",
10+
"transport": "stdio",
11+
"command": "uv",
12+
"args": [
13+
"run",
14+
"code-index-mcp"
15+
],
16+
"links": {
17+
"documentation": "https://github.com/johnhuang316/code-index-mcp#readme",
18+
"source": "https://github.com/johnhuang316/code-index-mcp"
19+
},
20+
"capabilities": [
21+
"code-search",
22+
"symbol-indexing",
23+
"file-system"
24+
],
25+
"tags": [
26+
"fastmcp",
27+
"code-intelligence",
28+
"watcher"
29+
]
30+
}
31+
]
32+
}

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,21 @@ Linux and macOS already expose the required XDG paths and `HOME`, so you can usu
8787
table there.
8888
Add overrides only if you run the CLI inside a restricted container.
8989

90+
### FastMCP & Discovery Manifests
91+
92+
- Run `fastmcp run fastmcp.json` to launch the server via [FastMCP](https://fastmcp.wiki/) with
93+
the correct source entrypoint and dependency metadata. Pass `--project-path` (or call the
94+
`set_project_path` tool after startup) so the index boots against the right repository.
95+
- Serve or copy `.well-known/mcp.json` to share a standards-compliant MCP manifest. Clients that
96+
support the `.well-known` convention (e.g., Claude Desktop, Codex CLI) can import this file
97+
directly instead of crafting configs manually.
98+
- Publish `.well-known/mcp.llmfeed.json` when you want to expose the richer LLM Feed metadata.
99+
It references the same `code-index` server definition plus documentation/source links, which
100+
helps registries present descriptions, tags, and capabilities automatically.
101+
102+
When sharing the manifests, remind consumers to supply `--project-path` (or to call
103+
`set_project_path`) so the server indexes the intended repository.
104+
90105
## Typical Use Cases
91106

92107
**Code Review**: "Find all places using the old API"

docs/mcp-restart-playbook.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# MCP Restart Playbook (November 10, 2025)
2+
3+
This runbook is for the first LLM/agent session *after* the MCP server restarts (for example, after bumping dependencies or recycling the FastMCP process). Follow every step in order so we quickly regain context, validate the upgraded toolchain, and communicate status to the rest of the team.
4+
5+
---
6+
7+
## 1. Current Snapshot
8+
- **Branch**: `mcp-upgrade-notes`
9+
- **Python**: 3.13.2 (uv-managed)
10+
- **Key dependency**: `mcp>=1.21.0,<2.0.0` (synced across `pyproject.toml`, `requirements.txt`, and `uv.lock`)
11+
- **Latest validation**: `uv run pytest` — 16 tests passed on **November 10, 2025 @ 02:05 UTC**
12+
- **Reference doc**: `docs/mcp-upgrade-notes.md` (rationale, API deltas, validation checklist)
13+
14+
If any of these details drift (new branch, newer SDK, etc.) update this file before handing off.
15+
16+
---
17+
18+
## 2. Post-Restart MCP Calls (must run all tools)
19+
Run through every exposed MCP primitive to guarantee parity after restart. Use the table below as a checklist and record each response summary.
20+
21+
| # | Tool | Minimum Input | Expected outcome |
22+
|---|------|---------------|------------------|
23+
| 1 | `set_project_path` | `path="C:\Users\p10362321\project\code-index-mcp"` | Indexed ~149 files; watcher initialized. |
24+
| 2 | `build_deep_index` | - | Project re-indexed. Found ~149 files / ~1,070 symbols. |
25+
| 3 | `search_code_advanced` | `pattern="FastMCP", file_pattern="src/**/*.py", max_results=20` | Hits in `server.py` plus pagination metadata. |
26+
| 4 | `find_files` | `pattern="tests/**/*.py"` | Returns 10 test modules. |
27+
| 5 | `get_file_summary` | `file_path="src/code_index_mcp/server.py"` | ~390 lines, 20+ functions reported. |
28+
| 6 | `refresh_index` | - | Shallow index re-built with ~149 files. |
29+
| 7 | `get_settings_info` | - | Shows temp/settings dirs, writable=true. |
30+
| 8 | `create_temp_directory` | - | Confirms directory exists/created. |
31+
| 9 | `check_temp_directory` | - | Lists `index.db`, `index.msgpack`, `index.shallow.json`. |
32+
|10 | `clear_settings` | - | Project settings, index, and cache have been cleared (rerun #1 + #2). |
33+
|11 | `refresh_search_tools` | - | Available: ['ripgrep', 'basic']; preferred: ripgrep. |
34+
|12 | `get_file_watcher_status` | - | status: active, debounce_seconds=6. |
35+
|13 | `configure_file_watcher` | `enabled=True, debounce_seconds=6` | Confirmation message (restart may be required). |
36+
37+
Notes:
38+
- After running `clear_settings`, immediately repeat `set_project_path` + `build_deep_index` to restore context before proceeding.
39+
- If any tool fails, stop the playbook, capture output, and escalate before continuing.
40+
41+
Log each response summary in the session notes so the next engineer knows everything is green.
42+
43+
---
44+
45+
## 3. CLI / End-to-End Smoke
46+
Run these in the repo root once the MCP tools succeed:
47+
48+
```powershell
49+
uv run code-index-mcp --project-path C:\Users\p10362321\project\code-index-mcp
50+
uv run pytest
51+
```
52+
53+
- Treat any warning or stderr output as a blocker.
54+
- Capture timestamps + durations; attach to release prep if we are close to tagging.
55+
56+
---
57+
58+
## 4. Communicate Status
59+
When handing the session back to the team, summarize:
60+
61+
- **SDK state**: Confirm we are still on MCP 1.21.0 (with context injection + capability helpers).
62+
- **Tool cache**: Mention that clients should re-cache tool lists after restart (FastMCP now enforces metadata changes).
63+
- **Known issues**: Note any skipped steps, flaky tests, or manual interventions.
64+
- **Next action**: “Ready for release prep” or “Need follow-up on X” — whichever applies after the smoke tests.
65+
66+
---
67+
68+
## 5. Troubleshooting Quick Reference
69+
- **`set_project_path` fails** → Ensure the repo path is accessible (sandbox permissions) and no other agent locked `index.db`. Run `clear_settings()` then retry.
70+
- **Search returns zero results** → Run `refresh_search_tools()`; if ripgrep missing, fall back to `basic` and flag the infra team.
71+
- **Watcher inactive** → Call `configure_file_watcher(enabled=True)` and `refresh_index()`. Document if it remains inactive.
72+
- **CLI smoke exits non-zero** → Capture full stdout/stderr, file an issue linked to `docs/mcp-upgrade-notes.md`, and pause release work.
73+
74+
Keep this section updated with any new gotchas discovered during restarts.
75+
76+
---
77+
78+
## 6. Hand-off Checklist
79+
- [ ] Steps 1–4 executed and logged in the current session.
80+
- [ ] Any deviations documented (include timestamps + command output).
81+
- [ ] This playbook reviewed/updated if procedures changed.
82+
83+
If all boxes are checked, the MCP server is considered healthy and ready for normal development or release activities.

docs/mcp-upgrade-notes.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# MCP Upgrade Notes (November 2025)
2+
3+
## Why this upgrade matters
4+
- `mcp` 1.21.0 was published to PyPI on 2025-11-06, so we are at least 17 point releases behind the current SDK and missing recent transport, auth, and client-surface fixes.
5+
- The MCP governance group will cut the next specification release on 2025-11-25 (RC on 2025-11-11), so validating 1.21.0 now keeps us aligned ahead of another protocol bump.
6+
7+
## Dependency & packaging considerations
8+
1. Run `uv lock --upgrade mcp` (or equivalent) so `uv.lock` stops pinning 1.4.1 and picks up the 1.21.0 wheels plus their refreshed transitive set (Starlette 0.49.1, AnyIO/HTTPX upgrades, etc.).
9+
2. Re-run `uv run pytest` and our smoke commands (`uv run code-index-mcp --project-path <repo>`) because AnyIO cancellation semantics and Starlette ASGI changes can surface subtle regressions in watcher services.
10+
3. Publish the lockfile and version bumps together; our release checklist requires pyproject + package __init__ + uv.lock to stay in sync.
11+
12+
## API & runtime changes to verify
13+
- SEP-985 landed in 1.21.0, adding OAuth-protected resource metadata fallback: confirm our SettingsService handles `WWW-Authenticate` responses and that CLI flags surface any required bearer tokens.
14+
- `ClientSession.get_server_capabilities()` is new; if clients or integration tests introspect capabilities manually, migrate to this helper.
15+
- Starlette 0.49.1 ships tighter ASGI scope validation; double-check our SSE transport and progress notifications.
16+
17+
## Recommended practices for 1.21.x
18+
1. **Depend on Context injection, not globals.** Annotate `ctx: Context` parameters so FastMCP injects the request context automatically instead of calling `mcp.get_context()` directly; this keeps us compatible with async-only handlers and future dependency-injection changes.
19+
2. **Cache expensive tool listings in clients.** Newer agents (OpenAI Agents SDK, Claude Desktop) call `list_tools()` on every run; set `cache_tools_list=True` only when our tool roster is static and call `invalidate_tools_cache()` after deployments.
20+
3. **Respect capability negotiation each session.** Protocol version 2025-06-18 remains current, and version negotiation happens during `initialize`; ensure our server exposes accurate `capabilities` metadata and gracefully errors when clients offer only future versions.
21+
4. **Stay ahead of November spec changes.** The upcoming 2025-11-25 spec focuses on additional security hardening. Schedule time to exercise the RC (available 2025-11-11) so we can absorb any required surface changes early.
22+
5. **Document OAuth and transport choices.** With SEP-985 and other auth SEPs in flight, record which flows (`device`, `jwt-bearer`, etc.) each deployment expects, and prefer the Streamable HTTP transport when exposing remote servers to benefit from the latest security guidance.
23+
24+
## Validation checklist before merging
25+
- [ ] Lockfile regenerated (`uv lock --upgrade mcp`) and `uv run python -m code_index_mcp.server --help` still succeeds.
26+
- [ ] `uv run code-index-mcp --project-path <repo>` exercises `set_project_path`, `build_deep_index`, and `search_code_advanced` end-to-end.
27+
- [ ] Smoke Claude Desktop / Codex CLI against the upgraded server; confirm resources + tools enumerate and that tool caching behaves as expected.
28+
- [ ] Update release notes + AGENTS.md summary once 1.21.x is verified in staging.

fastmcp.json

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"$schema": "https://fastmcp.wiki/en/schemas/fastmcp.json",
3+
"name": "Code Index MCP",
4+
"description": "Indexes a local repository and exposes search, indexing, and file utilities via the Model Context Protocol.",
5+
"license": "MIT",
6+
"keywords": [
7+
"mcp",
8+
"code-index",
9+
"search",
10+
"fastmcp"
11+
],
12+
"links": [
13+
{
14+
"rel": "source",
15+
"href": "https://github.com/johnhuang316/code-index-mcp"
16+
},
17+
{
18+
"rel": "documentation",
19+
"href": "https://github.com/johnhuang316/code-index-mcp#readme"
20+
}
21+
],
22+
"source": {
23+
"path": "src/code_index_mcp/server.py",
24+
"entrypoint": "mcp"
25+
},
26+
"environment": {
27+
"python": ">=3.10",
28+
"dependencies": [
29+
"mcp>=1.21.0,<2.0.0",
30+
"watchdog>=3.0.0",
31+
"tree-sitter>=0.20.0",
32+
"tree-sitter-javascript>=0.20.0",
33+
"tree-sitter-typescript>=0.20.0",
34+
"tree-sitter-java>=0.20.0",
35+
"tree-sitter-zig>=0.20.0",
36+
"pathspec>=0.12.1",
37+
"msgpack>=1.0.0"
38+
]
39+
},
40+
"deployment": {
41+
"transport": "stdio"
42+
}
43+
}

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ authors = [
1313
{name = "johnhuang316"}
1414
]
1515
dependencies = [
16-
"mcp>=0.3.0",
16+
"mcp>=1.21.0,<2.0.0",
1717
"watchdog>=3.0.0",
1818
"tree-sitter>=0.20.0",
1919
"tree-sitter-javascript>=0.20.0",

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
mcp>=0.3.0
1+
mcp>=1.21.0,<2.0.0
22
watchdog>=3.0.0
33
protobuf>=4.21.0
44
tree-sitter>=0.20.0

src/code_index_mcp/server.py

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,7 @@
3131
from .services.index_management_service import IndexManagementService
3232
from .services.code_intelligence_service import CodeIntelligenceService
3333
from .services.system_management_service import SystemManagementService
34-
from .utils import (
35-
handle_mcp_resource_errors, handle_mcp_tool_errors
36-
)
34+
from .utils import handle_mcp_tool_errors
3735

3836
# Setup logging without writing to files
3937
def setup_indexing_performance_logging():
@@ -126,27 +124,6 @@ async def indexer_lifespan(_server: FastMCP) -> AsyncIterator[CodeIndexerContext
126124
# Create the MCP server with lifespan manager
127125
mcp = FastMCP("CodeIndexer", lifespan=indexer_lifespan, dependencies=["pathlib"])
128126

129-
# ----- RESOURCES -----
130-
131-
@mcp.resource("config://code-indexer")
132-
@handle_mcp_resource_errors
133-
def get_config() -> str:
134-
"""Get the current configuration of the Code Indexer."""
135-
ctx = mcp.get_context()
136-
return ProjectManagementService(ctx).get_project_config()
137-
138-
@mcp.resource("files://{file_path}")
139-
@handle_mcp_resource_errors
140-
def get_file_content(file_path: str) -> str:
141-
"""Get the content of a specific file."""
142-
ctx = mcp.get_context()
143-
# Use FileService for simple file reading - this is appropriate for a resource
144-
return FileService(ctx).get_file_content(file_path)
145-
146-
# Removed: structure://project resource - not necessary for most workflows
147-
# Removed: settings://stats resource - this information is available via get_settings_info() tool
148-
# and is more of a debugging/technical detail rather than context AI needs
149-
150127
# ----- TOOLS -----
151128

152129
@mcp.tool()

src/code_index_mcp/utils/error_handler.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,7 @@ def handle_mcp_resource_errors(func: Callable) -> Callable:
7676
Example:
7777
@mcp.resource("config://code-indexer")
7878
@handle_mcp_resource_errors
79-
def get_config() -> str:
80-
ctx = mcp.get_context()
79+
def get_config(ctx: Context) -> str:
8180
from ..services.project_management_service import ProjectManagementService
8281
return ProjectManagementService(ctx).get_project_config()
8382
"""

0 commit comments

Comments
 (0)