fix(mcp): remove legacy ingest upload tools

Remove the old chunked upload MCP tools from the remote tool surface so agents only see the simplified upload paths: HTTP multipart and ingest_file_base64.

Update docs and agent rules to stop advertising the chunked fallback while keeping staged uploads outside the vault and behind the existing ingest gate.

Validation: python3 -m unittest discover -v; python3 -m py_compile obsidian_wiki/mcp_server.py tests/test_mcp_server_remote.py; git diff --check
This commit is contained in:
Codex
2026-07-05 16:35:45 +00:00
parent d7daf2f210
commit 75dea2cfaf
4 changed files with 6 additions and 42 deletions
+1 -1
View File
@@ -130,7 +130,7 @@ See `wiki-query` and `wiki-export` skills for how the filter is applied.
- **Keep product lookup fields explicit.** Carry forward `bjd_part_numbers`, `competitor_part_numbers`, `series`, `pitch`, `pin_count`, `product_lines`, `customers`, `competitors`, `standards`, `business_categories`, `related_pages`, and `catalog_paths` whenever they are known.
- **Merge, do not overwrite.** Automatic identifier extraction may add terms, but it must not discard curated registry metadata. Registry values are the durable source for future index rebuilds and remote MCP lookup.
- **Prefer precise identifiers in search ranking.** Exact or prefix matches in structured part-number and series fields should rank above incidental filename substrings such as timestamps or archive hashes.
- **Keep remote ingest gated.** MCP ingest tools are write-capable and must remain disabled unless the service config explicitly enables the `ingest` tool group via `OBSIDIAN_MCP_ENABLED_TOOLS=file-assets,ingest`, `mcp_service.sh tools enable ingest`, or `mcp_service.sh start --enable-ingest`. Uploaded files must stage outside the vault under the MCP runtime root; `wiki-ingest` is responsible for accepting, archiving, and indexing sources inside the vault. Prefer the HTTP multipart endpoint `/mcp-ingest/uploads` for remote file transfer, then `ingest_file_base64` for small files, and keep chunked upload tools only as a compatibility fallback. They may launch local OpenCode only through the fixed `/wiki-ingest` prompt; never expose arbitrary prompt or shell execution through MCP. Remote ingest must keep the OpenCode readiness preflight in front of job launch, and `check_ingest_opencode_readiness(run_smoke_test=true)` should stay available for operators to verify that OpenCode can load the project `wiki-ingest` skill before accepting uploads.
- **Keep remote ingest gated.** MCP ingest tools are write-capable and must remain disabled unless the service config explicitly enables the `ingest` tool group via `OBSIDIAN_MCP_ENABLED_TOOLS=file-assets,ingest`, `mcp_service.sh tools enable ingest`, or `mcp_service.sh start --enable-ingest`. Uploaded files must stage outside the vault under the MCP runtime root; `wiki-ingest` is responsible for accepting, archiving, and indexing sources inside the vault. Use the HTTP multipart endpoint `/mcp-ingest/uploads` for remote file transfer, or `ingest_file_base64` for small files when a client cannot make multipart HTTP requests. Do not expose chunked upload tools in the MCP tool surface. They may launch local OpenCode only through the fixed `/wiki-ingest` prompt; never expose arbitrary prompt or shell execution through MCP. Remote ingest must keep the OpenCode readiness preflight in front of job launch, and `check_ingest_opencode_readiness(run_smoke_test=true)` should stay available for operators to verify that OpenCode can load the project `wiki-ingest` skill before accepting uploads.
## Core Principles
+2 -5
View File
@@ -402,14 +402,11 @@ This adds write-capable MCP tools to the same `wiki-file-assets` server and bear
- `get_ingest_upload_instructions` — returns the preferred upload methods, HTTP endpoint path, fields, limits, and curl example for remote agents.
- `ingest_file_base64` — uploads one complete base64 file and optionally starts the local OpenCode ingest job; useful for small files or MCP clients that cannot make multipart HTTP requests.
- `create_ingest_upload` — reserves a controlled runtime staging path for one uploaded file.
- `append_ingest_upload_chunk` — appends base64 file chunks; defaults to 4MB decoded chunks.
- `complete_ingest_upload` — verifies declared size and SHA-256.
- `check_ingest_opencode_readiness` — verifies the local OpenCode binary, required run flags, project ingest skills, and optionally runs a no-write smoke test that confirms `wiki-ingest` can be loaded.
- `start_ingest_job` — queues a local `opencode run --auto --format json` job with a fixed `/wiki-ingest` prompt for the completed uploads.
- `get_ingest_job_status`, `get_ingest_job_result`, `cancel_ingest_job` — inspect or cancel the local job.
For binary files, prefer the HTTP upload endpoint over manual chunk tools:
For binary files, use the HTTP upload endpoint:
```bash
curl -H "Authorization: Bearer <long-random-token>" \
@@ -420,7 +417,7 @@ curl -H "Authorization: Bearer <long-random-token>" \
http://127.0.0.1:8765/mcp-ingest/uploads
```
The endpoint accepts repeated `files` fields plus optional `project`, `doc_type_hint`, `note`, and `start_job` fields. It uses the same bearer token as `/mcp`; there is no second token to manage. Keep `create_ingest_upload` / `append_ingest_upload_chunk` / `complete_ingest_upload` as a fallback for MCP clients that cannot call the HTTP endpoint and cannot send a complete base64 file in one tool call.
The endpoint accepts repeated `files` fields plus optional `project`, `doc_type_hint`, `note`, and `start_job` fields. It uses the same bearer token as `/mcp`; there is no second token to manage. For MCP clients that cannot make HTTP multipart requests, use `ingest_file_base64` for small files.
Run `check_ingest_opencode_readiness` before the first remote upload. Use `run_smoke_test: true` when you want OpenCode itself to prove it can load the project `wiki-ingest` skill; otherwise the static preflight is also run automatically before every `start_ingest_job`.
-33
View File
@@ -235,12 +235,6 @@ def create_server(
"best_for": "small files or MCP clients that cannot make HTTP multipart requests",
"start_job_default": True,
},
"chunked_fallback_tools": [
"create_ingest_upload",
"append_ingest_upload_chunk",
"complete_ingest_upload",
"start_ingest_job",
],
"limits": {
"max_file_bytes": ingest_manager.max_file_bytes,
"max_chunk_bytes": ingest_manager.max_chunk_bytes,
@@ -276,33 +270,6 @@ def create_server(
job = ingest_manager.start_ingest_job([upload["upload_id"]], note=note) if start_job else None
return {"upload": upload, "job": job}
@server.tool()
def create_ingest_upload(
file_name: str,
size_bytes: int,
sha256: str,
project: str | None = None,
doc_type_hint: str | None = None,
) -> dict[str, Any]:
"""Create a controlled upload slot for a file that will later be ingested locally."""
return ingest_manager.create_upload(
file_name=file_name,
size_bytes=size_bytes,
sha256=sha256,
project=project,
doc_type_hint=doc_type_hint,
)
@server.tool()
def append_ingest_upload_chunk(upload_id: str, offset: int, data_base64: str) -> dict[str, Any]:
"""Append one base64 chunk to an MCP ingest upload."""
return ingest_manager.append_upload_chunk(upload_id, offset=offset, data_base64=data_base64)
@server.tool()
def complete_ingest_upload(upload_id: str) -> dict[str, Any]:
"""Finalize an uploaded file after validating size and sha256."""
return ingest_manager.complete_upload(upload_id)
@server.tool()
def start_ingest_job(upload_ids: list[str], note: str | None = None) -> dict[str, Any]:
"""Start or queue a local OpenCode wiki-ingest job for completed uploads."""
+3 -3
View File
@@ -291,9 +291,9 @@ class RemoteMcpServerTests(unittest.TestCase):
)
self.assertIsInstance(server, FakeMCP)
self.assertIn("create_ingest_upload", FakeMCP.tool_names)
self.assertIn("append_ingest_upload_chunk", FakeMCP.tool_names)
self.assertIn("complete_ingest_upload", FakeMCP.tool_names)
self.assertNotIn("create_ingest_upload", FakeMCP.tool_names)
self.assertNotIn("append_ingest_upload_chunk", FakeMCP.tool_names)
self.assertNotIn("complete_ingest_upload", FakeMCP.tool_names)
self.assertIn("start_ingest_job", FakeMCP.tool_names)
self.assertIn("get_ingest_job_status", FakeMCP.tool_names)
self.assertIn("get_ingest_job_result", FakeMCP.tool_names)