diff --git a/AGENTS.md b/AGENTS.md index 05bb7be..0fa0c72 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -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 diff --git a/README.md b/README.md index 11a0ac5..cc45df7 100644 --- a/README.md +++ b/README.md @@ -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 " \ @@ -420,7 +417,7 @@ curl -H "Authorization: Bearer " \ 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`. diff --git a/obsidian_wiki/mcp_server.py b/obsidian_wiki/mcp_server.py index bd37636..d8dfe8e 100644 --- a/obsidian_wiki/mcp_server.py +++ b/obsidian_wiki/mcp_server.py @@ -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.""" diff --git a/tests/test_mcp_server_remote.py b/tests/test_mcp_server_remote.py index 0c6fa8e..fd34050 100644 --- a/tests/test_mcp_server_remote.py +++ b/tests/test_mcp_server_remote.py @@ -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)