Skip to content

Commit acc13fe

Browse files
committed
partners/integration mcp
1 parent f22a613 commit acc13fe

File tree

8 files changed

+3614
-10
lines changed

8 files changed

+3614
-10
lines changed

scripts/mcp-eval/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ npx tsx scripts/mcp-eval/run-eval.ts --tag query
3232

3333
# Use a different MCP endpoint
3434
MCP_URL=https://tanstack.com/api/mcp npx tsx scripts/mcp-eval/run-eval.ts
35+
36+
# Authenticate with an API key (required for production)
37+
MCP_API_KEY=your-api-key MCP_URL=http://localhost:3000/api/mcp npx tsx scripts/mcp-eval/run-eval.ts
3538
```
3639

3740
## Test Case Structure

scripts/mcp-eval/results.json

Lines changed: 3247 additions & 0 deletions
Large diffs are not rendered by default.

scripts/mcp-eval/run-eval.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import testCases from './test-cases.json'
1414

1515
const MCP_URL = process.env.MCP_URL || 'http://localhost:3001/api/mcp'
16+
const MCP_API_KEY = process.env.MCP_API_KEY
1617

1718
interface SearchResult {
1819
title: string
@@ -50,13 +51,19 @@ interface TestResult {
5051
}
5152

5253
async function callMcp(method: string, params: object): Promise<McpResponse> {
54+
const headers: Record<string, string> = {
55+
'Content-Type': 'application/json',
56+
Accept: 'application/json, text/event-stream',
57+
}
58+
59+
if (MCP_API_KEY) {
60+
headers['Authorization'] = `Bearer ${MCP_API_KEY}`
61+
}
62+
5363
// First initialize
5464
await fetch(MCP_URL, {
5565
method: 'POST',
56-
headers: {
57-
'Content-Type': 'application/json',
58-
Accept: 'application/json, text/event-stream',
59-
},
66+
headers,
6067
body: JSON.stringify({
6168
jsonrpc: '2.0',
6269
id: 0,
@@ -72,10 +79,7 @@ async function callMcp(method: string, params: object): Promise<McpResponse> {
7279
// Then call the tool
7380
const response = await fetch(MCP_URL, {
7481
method: 'POST',
75-
headers: {
76-
'Content-Type': 'application/json',
77-
Accept: 'application/json, text/event-stream',
78-
},
82+
headers,
7983
body: JSON.stringify({
8084
jsonrpc: '2.0',
8185
id: 1,

scripts/mcp-eval/test-cases.json

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1798,6 +1798,160 @@
17981798
"idealSearchQueries": ["cms start", "headless cms tanstack"],
17991799
"correctAnswerMustInclude": ["Strapi"],
18001800
"notes": "Partner discovery test. Strapi is the CMS partner."
1801+
},
1802+
1803+
{
1804+
"id": "ecosystem-postgres-alias",
1805+
"question": "I need a postgres database for my TanStack Start app",
1806+
"difficulty": "easy",
1807+
"tags": ["start", "database", "ecosystem", "mcp-tool"],
1808+
"expectedDocs": [
1809+
{
1810+
"library": "start",
1811+
"path": "framework/react/guide/databases",
1812+
"required": true,
1813+
"reason": "Databases guide"
1814+
}
1815+
],
1816+
"idealSearchQueries": ["databases guide"],
1817+
"correctAnswerMustInclude": ["Neon"],
1818+
"notes": "Tests category alias resolution. 'postgres' should resolve to 'database' category. MCP tool: get_ecosystem_recommendations({ category: 'postgres' })"
1819+
},
1820+
{
1821+
"id": "ecosystem-login-alias",
1822+
"question": "How do I add login functionality to my app?",
1823+
"difficulty": "easy",
1824+
"tags": ["start", "auth", "ecosystem", "mcp-tool"],
1825+
"expectedDocs": [
1826+
{
1827+
"library": "start",
1828+
"path": "framework/react/guide/authentication-overview",
1829+
"required": true,
1830+
"reason": "Auth overview"
1831+
}
1832+
],
1833+
"idealSearchQueries": ["authentication overview"],
1834+
"correctAnswerMustInclude": ["Clerk", "WorkOS"],
1835+
"notes": "Tests category alias resolution. 'login' should resolve to 'auth' category. MCP tool: get_ecosystem_recommendations({ category: 'login' })"
1836+
},
1837+
{
1838+
"id": "ecosystem-serverless-alias",
1839+
"question": "What serverless hosting options work with TanStack Start?",
1840+
"difficulty": "easy",
1841+
"tags": ["start", "deployment", "ecosystem", "mcp-tool"],
1842+
"expectedDocs": [
1843+
{
1844+
"library": "start",
1845+
"path": "framework/react/guide/hosting",
1846+
"required": true,
1847+
"reason": "Hosting guide"
1848+
}
1849+
],
1850+
"idealSearchQueries": ["hosting guide"],
1851+
"correctAnswerMustInclude": ["Cloudflare", "Netlify"],
1852+
"notes": "Tests category alias resolution. 'serverless' should resolve to 'deployment' category. MCP tool: get_ecosystem_recommendations({ category: 'serverless' })"
1853+
},
1854+
{
1855+
"id": "ecosystem-error-tracking-alias",
1856+
"question": "I need error tracking for production",
1857+
"difficulty": "easy",
1858+
"tags": ["start", "monitoring", "ecosystem", "mcp-tool"],
1859+
"expectedDocs": [
1860+
{
1861+
"library": "start",
1862+
"path": "framework/react/guide/observability",
1863+
"required": false,
1864+
"reason": "Observability guide"
1865+
}
1866+
],
1867+
"idealSearchQueries": ["observability", "error monitoring"],
1868+
"correctAnswerMustInclude": ["Sentry"],
1869+
"notes": "Tests category alias resolution. 'error tracking' should resolve to 'monitoring' category. MCP tool: get_ecosystem_recommendations({ category: 'error-tracking' })"
1870+
},
1871+
{
1872+
"id": "ecosystem-library-filter",
1873+
"question": "What ecosystem integrations are available for TanStack Table?",
1874+
"difficulty": "easy",
1875+
"tags": ["table", "ecosystem", "mcp-tool"],
1876+
"expectedDocs": [
1877+
{
1878+
"library": "table",
1879+
"path": "introduction",
1880+
"required": true,
1881+
"reason": "Table introduction"
1882+
}
1883+
],
1884+
"idealSearchQueries": ["table introduction"],
1885+
"correctAnswerMustInclude": ["AG Grid"],
1886+
"notes": "Tests library filter. MCP tool: get_ecosystem_recommendations({ library: 'table' })"
1887+
},
1888+
{
1889+
"id": "ecosystem-sso-enterprise",
1890+
"question": "I need SSO and enterprise authentication features",
1891+
"difficulty": "medium",
1892+
"tags": ["start", "auth", "enterprise", "ecosystem", "mcp-tool"],
1893+
"expectedDocs": [
1894+
{
1895+
"library": "start",
1896+
"path": "framework/react/guide/authentication-overview",
1897+
"required": true,
1898+
"reason": "Auth overview with WorkOS for enterprise"
1899+
}
1900+
],
1901+
"idealSearchQueries": ["authentication overview", "workos sso"],
1902+
"correctAnswerMustInclude": ["WorkOS"],
1903+
"notes": "Tests SSO/enterprise auth. 'sso' alias should resolve to 'auth'. WorkOS specifically handles enterprise features."
1904+
},
1905+
{
1906+
"id": "ecosystem-realtime-database",
1907+
"question": "I need a real-time database with live queries",
1908+
"difficulty": "medium",
1909+
"tags": ["start", "database", "realtime", "ecosystem", "mcp-tool"],
1910+
"expectedDocs": [
1911+
{
1912+
"library": "start",
1913+
"path": "framework/react/guide/databases",
1914+
"required": true,
1915+
"reason": "Databases guide"
1916+
}
1917+
],
1918+
"idealSearchQueries": ["databases guide", "convex realtime"],
1919+
"correctAnswerMustInclude": ["Convex"],
1920+
"notes": "Tests real-time database needs. Convex specifically offers real-time features."
1921+
},
1922+
{
1923+
"id": "ecosystem-rate-limiting",
1924+
"question": "How do I add rate limiting to my API?",
1925+
"difficulty": "medium",
1926+
"tags": ["api", "rate-limiting", "ecosystem", "mcp-tool"],
1927+
"expectedDocs": [
1928+
{
1929+
"library": "pacer",
1930+
"path": "overview",
1931+
"required": false,
1932+
"reason": "Pacer overview for rate limiting"
1933+
}
1934+
],
1935+
"idealSearchQueries": ["rate limiting", "pacer"],
1936+
"correctAnswerMustInclude": ["Unkey"],
1937+
"notes": "Tests API/rate-limiting category. Unkey is the API management partner."
1938+
},
1939+
{
1940+
"id": "ecosystem-offline-sync",
1941+
"question": "I need offline-first sync capabilities for my app",
1942+
"difficulty": "medium",
1943+
"tags": ["db", "database", "sync", "ecosystem", "mcp-tool"],
1944+
"expectedDocs": [
1945+
{
1946+
"library": "db",
1947+
"path": "overview",
1948+
"required": false,
1949+
"reason": "TanStack DB overview"
1950+
}
1951+
],
1952+
"idealSearchQueries": ["tanstack db", "sync"],
1953+
"correctAnswerMustInclude": ["Electric", "PowerSync"],
1954+
"notes": "Tests sync/offline capabilities. Electric and PowerSync are TanStack DB partners."
18011955
}
18021956
]
18031957
}

src/db/schema.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1016,7 +1016,7 @@ export const mcpApiKeys = pgTable(
10161016
// Optional user association
10171017
userId: uuid('user_id').references(() => users.id, { onDelete: 'cascade' }),
10181018
// Rate limit tier (requests per minute)
1019-
rateLimitPerMinute: integer('rate_limit_per_minute').notNull().default(60),
1019+
rateLimitPerMinute: integer('rate_limit_per_minute').notNull().default(200),
10201020
// Key state
10211021
isActive: boolean('is_active').notNull().default(true),
10221022
lastUsedAt: timestamp('last_used_at', { withTimezone: true, mode: 'date' }),

src/mcp/server.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ import {
2727
getNpmPackageDownloads,
2828
getNpmPackageDownloadsSchema,
2929
} from './tools/get-npm-package-downloads'
30+
import {
31+
getEcosystemRecommendations,
32+
getEcosystemRecommendationsSchema,
33+
} from './tools/get-ecosystem-recommendations'
3034

3135
export type McpAuthContext = {
3236
userId: string
@@ -439,5 +443,40 @@ export function createMcpServer(authContext?: McpAuthContext) {
439443
},
440444
)
441445

446+
// ============================================================================
447+
// Ecosystem Tools
448+
// ============================================================================
449+
450+
// Register get_ecosystem_recommendations tool
451+
server.tool(
452+
'get_ecosystem_recommendations',
453+
'Get ecosystem integration recommendations (Neon, Clerk, Convex, AG Grid, Netlify, Cloudflare, Sentry, Prisma, Strapi, etc.). Filter by category (database, auth, deployment, monitoring, cms, api, data-grid) or by TanStack library. Supports aliases like postgres→database, login→auth, serverless→deployment. USE THIS TOOL when users ask about: where to host/deploy, which database to use, authentication solutions, error monitoring, CMS options, or any infrastructure/tooling recommendations for TanStack apps.',
454+
getEcosystemRecommendationsSchema.shape,
455+
async (args) => {
456+
try {
457+
const parsed = getEcosystemRecommendationsSchema.parse(args)
458+
const result = await getEcosystemRecommendations(parsed)
459+
return {
460+
content: [
461+
{
462+
type: 'text' as const,
463+
text: JSON.stringify(result, null, 2),
464+
},
465+
],
466+
}
467+
} catch (error) {
468+
return {
469+
content: [
470+
{
471+
type: 'text' as const,
472+
text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`,
473+
},
474+
],
475+
isError: true,
476+
}
477+
}
478+
},
479+
)
480+
442481
return server
443482
}

0 commit comments

Comments
 (0)