Vault.MCP / scripts /test_mcp_tools.py
bigwolfe
security
69f247d
#!/usr/bin/env python3
"""Exercise all MCP tools exposed by the hosted server."""
from __future__ import annotations
import argparse
import asyncio
import json
import os
import sys
import uuid
from typing import Any, Dict
from fastmcp.client import Client, StreamableHttpTransport
from fastmcp.client.client import ToolError
def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(description="Test MCP HTTP tools end-to-end")
parser.add_argument(
"--url",
default=os.environ.get("MCP_URL", "https://YOUR_USERNAME-document-mcp.hf.space/mcp"),
help="Hosted MCP endpoint base URL",
)
parser.add_argument(
"--token",
default=os.environ.get("MCP_TOKEN"),
help="Bearer token for authentication (or set MCP_TOKEN env variable)",
)
parser.add_argument(
"--note",
default=f"mcp-test-{uuid.uuid4().hex}.md",
help="Temporary note path to create and delete during the test",
)
return parser
async def exercise_tools(url: str, token: str, note_path: str) -> Dict[str, Any]:
transport = StreamableHttpTransport(url=url, headers={"Authorization": f"Bearer {token}"})
async with Client(transport, name="multi-tenant-audit") as client:
results: Dict[str, Any] = {}
tools = await client.list_tools()
results["list_tools"] = [tool.name for tool in tools]
results["list_notes_before"] = await client.call_tool("list_notes", {})
# Read the welcome note if it exists
try:
results["read_note"] = await client.call_tool(
"read_note", {"path": "Welcome.md"}
)
except ToolError as exc:
results["read_note_error"] = str(exc)
# Create a temporary note
body = "# MCP Test\n\nThis note was created by the MCP HTTP audit script."
results["write_note"] = await client.call_tool(
"write_note",
{
"path": note_path,
"body": body,
"title": "MCP Test",
"metadata": {"tags": ["mcp", "audit"]},
},
)
# Search for the word "MCP"
results["search_notes"] = await client.call_tool(
"search_notes", {"query": "MCP", "limit": 10}
)
# Fetch backlinks for the welcome note (if present)
try:
results["get_backlinks"] = await client.call_tool(
"get_backlinks", {"path": "Welcome.md"}
)
except ToolError as exc:
results["get_backlinks_error"] = str(exc)
# Fetch tags
results["get_tags"] = await client.call_tool("get_tags", {})
# Delete the temporary note and show list afterwards
results["delete_note"] = await client.call_tool(
"delete_note", {"path": note_path}
)
results["list_notes_after"] = await client.call_tool("list_notes", {})
return results
def main() -> None:
parser = build_parser()
args = parser.parse_args()
if not args.token:
parser.error("Bearer token must be provided via --token or MCP_TOKEN env variable")
try:
results = asyncio.run(exercise_tools(args.url, args.token, args.note))
except Exception as exc: # pragma: no cover
print(f"Error exercising MCP tools: {exc}", file=sys.stderr)
raise SystemExit(1) from exc
json.dump(results, sys.stdout, indent=2, sort_keys=True)
print()
if __name__ == "__main__":
main()