Static source inference · medium confidence · evidence: Streamable HTTP
Current-spec patterns detected
Summary
This server presents a fundamentally flawed architecture: it is a pure FastAPI HTTP wrapper around file-fetching operations, but does NOT expose these endpoints as MCP tools. The server.py file contains no tool registration mechanism, no MCP protocol handlers, and no schema definitions. The endpoints are raw HTTP routes (GET /fetch_image_base64, GET /image/{file_id}.jpg, etc.), not registered tools. While the rubric description claims '6 total' tools with schemas and descriptions, the actual source code shows ZERO MCP tool registration. The endpoint docstrings exist (e.g., '將圖片轉成 base64 格式') but these are Python docstrings on FastAPI route handlers, not MCP tool definitions. Without explicit tool registration via an MCP server framework (e.g., using mcp.Tool, mcp.server.Server, or equivalent), the LLM cannot discover or invoke these as tools, they are only usable as raw HTTP endpoints. This is a critical architectural failure: the server is not an MCP server at all, merely a FastAPI HTTP service. Per the hard scoring rule, 'If you cannot see the actual tool definition in the source (only inferred): cap that tool's overall at 50.' Here, tool definitions are entirely inferred from HTTP routes and not explicitly registered, so all tools are capped at 50. However, the lack of MCP protocol implementation further reduces the overall definition quality score.
No MCP tool registration present. The server implements FastAPI HTTP routes, not MCP tools. No MCP protocol handler, no mcp.Tool definitions, no schema declarations. This is a raw HTTP service, not an MCP server.
No input schemas defined. All tools lack JSON Schema definitions for parameters. Bare FastAPI query parameters (url: str, file_id: str) are not self-documenting MCP input schemas.
Descriptions are in Chinese and extremely terse (under 20 chars when translated). Example: '支援 .jpg 圖片' = 'Supports .jpg images' (18 chars). Descriptions do not explain WHEN to use, WHAT problem is solved, or dependencies.
Recommendations
CRITICAL: Refactor as a true MCP server. Use the official Python MCP SDK (e.g., mcp >= 0.9). Register each endpoint as an explicit Tool with mcp.Tool(name, description, inputSchema). See https://github.com/modelcontextprotocol/python-sdk.
Add detailed input schemas to each tool using JSON Schema. Example for fetch_image_base64: inputSchema = { type: 'object', properties: { url: { type: 'string', description: 'HTTPS URL of the image to fetch. Must start with http:// or https://. Max 2048 chars.' } }, required: ['url'] }.
Expand tool descriptions from terse Chinese to ~100-150 character English explanations. Example: 'Fetch a remote image via URL and convert to base64 encoding. Useful for embedding images in LLM prompts. Returns base64-encoded content and MIME type.'
Add parameter descriptions. Example for 'file_id': 'Google Drive file ID (alphanumeric string, e.g. 1a2b3c4d5e). Call this only if you have already identified the file ID; otherwise use search tools first.'
Document output schema for each tool. Example for fetch_image_base64: outputSchema = { type: 'object', properties: { status: { enum: ['ok', 'error'] }, base64: { type: 'string', description: 'Base64-encoded image data' }, mimetype: { type: 'string' } } }.
Implement proper error messages. Instead of 'return {"status": "error", "message": str(e)}', return structured errors with guidance. Example: '{ "status": "error", "code": "INVALID_URL", "message": "URL must start with https://. Got: ftp://example.com", "retry": true }'.
No output schema documented. Tools return raw Response objects or JSON dicts without documented structure. LLMs cannot determine what fields to expect or how to chain results to downstream tools.
No input validation or constraints. 'url' parameter accepts any string, inviting invalid inputs. No enum, no regex pattern, no length limit. No guard against file:// URLs or SSRF attacks.
Error handling returns bare exception messages. Example: 'return {"status": "error", "message": str(e)}' exposes stack traces to LLMs. Per pattern: errors must tell the LLM what to do next, not just what failed. No retry guidance, no categorization (retryable vs fatal).
No authorization or permission gates. Any caller can fetch arbitrary Google Drive files via exposed file_id. No authentication, no scope declaration, no audit trail. Per pattern: destructive/sensitive tools must gate access.
No rate limiting. An agent in a retry loop can hammer the Google Drive API and external image URLs without throttling, risking service degradation and IP bans.
No timeout handling on external requests. requests.get() calls have no timeout parameter. Long-hanging upstream services will block the FastAPI worker indefinitely.
Add input validation: validate URLs match ^https?://, validate file_id matches ^[a-zA-Z0-9_-]{10,}$, reject data: and file: schemes to prevent SSRF attacks.
Add timeout to requests: requests.get(url, timeout=30) for external images, requests.get(drive_url, timeout=60) for Google Drive.
Add rate limiting per IP/caller. Use a simple in-memory or Redis-backed rate limiter (e.g., slowapi library). Limit to 10-20 requests/minute per client.
Add request logging and audit trail. Log caller (from X-Forwarded-For or auth header), tool name, parameters (sanitized), response status, and timestamp. Include in error responses for support debugging.
Clarify and separate tool responsibilities: fetch_image_base64 and fetch_image_proxy do overlapping things. Consider: 'fetch_remote_image' (generic URL fetch with format option) vs 'fetch_drive_image' (Google Drive specific). Each tool should do ONE thing.
Document the purpose of each tool in context. When should an LLM choose fetch_image_as_jpg vs fetch_image_proxy? Add WHEN clauses to descriptions to guide tool selection.
Add tool annotations (readOnlyHint, idempotentHint) if using MCP SDK >= 0.9. All 6 tools are read-only and idempotent, so mark them: readOnlyHint=true, idempotentHint=true.
Translate all Chinese docstrings to English. LLMs default to English reasoning; non-English descriptions cause confusion and poor tool selection.