|
| 1 | +apiVersion: toolhive.stacklok.dev/v1alpha1 |
| 2 | +kind: VirtualMCPServer |
| 3 | +metadata: |
| 4 | + name: vmcp-research |
| 5 | + namespace: toolhive-system |
| 6 | + annotations: |
| 7 | + toolhive.stacklok.dev/registry-export: "true" |
| 8 | + toolhive.stacklok.dev/registry-url: "http://$MCP_HOSTNAME/vmcp-research/mcp" |
| 9 | + toolhive.stacklok.dev/registry-description: | |
| 10 | + A vMCP server demonstrating a research workflow with a composite tool. |
| 11 | +spec: |
| 12 | + config: |
| 13 | + groupRef: research-tools |
| 14 | + telemetry: |
| 15 | + endpoint: mcp-collector.observability:4318 |
| 16 | + insecure: true |
| 17 | + serviceName: vmcp-research-server |
| 18 | + serviceVersion: "1.0.0" |
| 19 | + metricsEnabled: true |
| 20 | + tracingEnabled: true |
| 21 | + samplingRate: "1.0" |
| 22 | + aggregation: |
| 23 | + conflictResolution: prefix |
| 24 | + conflictResolutionConfig: |
| 25 | + prefixFormat: "{workload}_" |
| 26 | + tools: |
| 27 | + - workload: arxiv |
| 28 | + filter: |
| 29 | + - "list_papers" |
| 30 | + compositeTools: |
| 31 | + - name: research_topic |
| 32 | + description: Search arXiv for papers and read the top result |
| 33 | + parameters: |
| 34 | + type: object |
| 35 | + properties: |
| 36 | + query: |
| 37 | + type: string |
| 38 | + description: Research topic to search for |
| 39 | + required: |
| 40 | + - query |
| 41 | + steps: |
| 42 | + # Step 1: Search arXiv for papers matching the query |
| 43 | + - id: search |
| 44 | + tool: arxiv_search_papers |
| 45 | + arguments: |
| 46 | + query: "{{.params.query}}" |
| 47 | + max_results: 1 |
| 48 | + # Step 2: Download the paper (required before reading) |
| 49 | + # Note: fromJson is needed when the MCP server returns JSON as text |
| 50 | + # rather than structured content. This is common for servers that |
| 51 | + # don't fully support MCP's structuredContent field. |
| 52 | + - id: download |
| 53 | + tool: arxiv_download_paper |
| 54 | + arguments: |
| 55 | + paper_id: "{{(index (fromJson .steps.search.output.text).papers 0).id}}" |
| 56 | + dependsOn: [search] |
| 57 | + # Step 3: Read the downloaded paper content |
| 58 | + - id: read |
| 59 | + tool: arxiv_read_paper |
| 60 | + arguments: |
| 61 | + paper_id: "{{(index (fromJson .steps.search.output.text).papers 0).id}}" |
| 62 | + dependsOn: [download] |
| 63 | + incomingAuth: |
| 64 | + type: anonymous |
| 65 | + serviceType: ClusterIP |
| 66 | +--- |
| 67 | +apiVersion: gateway.networking.k8s.io/v1 |
| 68 | +kind: HTTPRoute |
| 69 | +metadata: |
| 70 | + name: vmcp-research-route |
| 71 | + namespace: toolhive-system |
| 72 | +spec: |
| 73 | + parentRefs: |
| 74 | + - name: traefik-gateway |
| 75 | + namespace: traefik |
| 76 | + rules: |
| 77 | + - matches: |
| 78 | + - path: |
| 79 | + type: PathPrefix |
| 80 | + value: /vmcp-research |
| 81 | + filters: |
| 82 | + - type: URLRewrite |
| 83 | + urlRewrite: |
| 84 | + path: |
| 85 | + type: ReplacePrefixMatch |
| 86 | + replacePrefixMatch: / |
| 87 | + backendRefs: |
| 88 | + - name: vmcp-vmcp-research |
| 89 | + port: 4483 |
0 commit comments