feat(mcp): queue local OpenCode ingest jobs
Add optional write-capable MCP ingest tools for chunked uploads, SHA-verified completion, and asynchronous local OpenCode wiki-ingest jobs. The tools remain disabled by default and are gated by OBSIDIAN_MCP_ENABLE_INGEST or mcp_service.sh start --enable-ingest. Remote clients can upload files into the vault inbox, start a restricted fixed-prompt ingest job, poll job status/result, and cancel queued or running work. The implementation keeps arbitrary prompt and shell execution out of the MCP surface. Validation: python3 -m unittest discover -v; python3 -m py_compile obsidian_wiki/mcp_ingest.py obsidian_wiki/mcp_server.py scripts/manage_mcp_service.py tests/test_mcp_ingest.py tests/test_mcp_server_remote.py tests/test_mcp_service.py; git diff --check.
This commit is contained in:
@@ -138,6 +138,54 @@ class RemoteMcpServerTests(unittest.TestCase):
|
||||
self.assertIn("list_file_assets", FakeMCP.tool_names)
|
||||
self.assertIn("get_file_asset_metadata", FakeMCP.tool_names)
|
||||
self.assertIn("how_to_use_wiki_file_assets", FakeMCP.prompt_names)
|
||||
self.assertNotIn("create_ingest_upload", FakeMCP.tool_names)
|
||||
|
||||
def test_create_server_registers_ingest_tools_when_enabled(self):
|
||||
class FakeMCP:
|
||||
tool_names = []
|
||||
|
||||
def __init__(self, _name, **_kwargs):
|
||||
pass
|
||||
|
||||
def tool(self):
|
||||
def decorator(func):
|
||||
self.tool_names.append(func.__name__)
|
||||
return func
|
||||
|
||||
return decorator
|
||||
|
||||
def resource(self, *_args, **_kwargs):
|
||||
def decorator(func):
|
||||
return func
|
||||
|
||||
return decorator
|
||||
|
||||
def prompt(self, *_args, **_kwargs):
|
||||
def decorator(func):
|
||||
return func
|
||||
|
||||
return decorator
|
||||
|
||||
with (
|
||||
tempfile.TemporaryDirectory() as tmp,
|
||||
patch.dict("sys.modules", {"mcp.server.fastmcp": type("Mod", (), {"FastMCP": FakeMCP})()}),
|
||||
):
|
||||
root = Path(tmp)
|
||||
server = mcp_server.create_server(
|
||||
vault_path=root / "vault",
|
||||
enable_ingest=True,
|
||||
project_root=root / "project",
|
||||
ingest_runtime_root=root / "runtime",
|
||||
)
|
||||
|
||||
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.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)
|
||||
self.assertIn("cancel_ingest_job", FakeMCP.tool_names)
|
||||
|
||||
def test_run_http_server_fails_before_server_creation_without_token(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
|
||||
Reference in New Issue
Block a user