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:
@@ -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
|
||||
|
||||
|
||||
@@ -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`.
|
||||
|
||||
|
||||
@@ -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."""
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user