Skip to content

Commit 187493d

Browse files
committed
feat(backend): add FastMCP framework support and handle missing package metadata
Add support for FastMCP Python framework in deployment validation and fix deployment failures for Python projects without pyproject.toml. Changes: - Add FastMCP package detection in runtime-detector.ts (requirements.txt and pyproject.toml) - Generate fallback package name from repository name when metadata.name is undefined - Handle Python projects with only requirements.txt (no pyproject.toml) - Add logging when fallback package name generation is used
1 parent 15c3d45 commit 187493d

File tree

2 files changed

+44
-7
lines changed

2 files changed

+44
-7
lines changed

services/backend/src/lib/deployment/runtime-detector.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,13 +137,28 @@ export class RuntimeDetector {
137137
line.trim() === 'mcp'
138138
);
139139

140+
// FastMCP framework (high-level MCP framework, 70% market share)
141+
const fastmcpLine = requirements.find(line =>
142+
line.trim().startsWith('fastmcp==') ||
143+
line.trim().startsWith('fastmcp>=') ||
144+
line.trim() === 'fastmcp'
145+
);
146+
147+
// Prioritize official SDK, but FastMCP is also a valid MCP framework
140148
if (mcpLine) {
141149
mcpSdkInfo = {
142150
detected: true,
143151
version: mcpLine?.split(/==|>=/)[1]?.trim(),
144152
package: 'mcp',
145153
runtime: 'python'
146154
};
155+
} else if (fastmcpLine) {
156+
mcpSdkInfo = {
157+
detected: true,
158+
version: fastmcpLine?.split(/==|>=/)[1]?.trim(),
159+
package: 'fastmcp',
160+
runtime: 'python'
161+
};
147162
}
148163
}
149164
} catch {
@@ -164,20 +179,32 @@ export class RuntimeDetector {
164179

165180
// If we haven't found MCP SDK in requirements.txt, check pyproject.toml
166181
if (!mcpSdkInfo) {
167-
// Check for "mcp" in dependencies (handles both "mcp" and "mcp>=1.0.0" formats)
182+
// Check for official "mcp" SDK (handles both "mcp" and "mcp>=1.0.0" formats)
168183
const hasMcp = /["']mcp["']/.test(content) || /["']mcp[><=]/.test(content);
169184

185+
// Check for FastMCP framework
186+
const hasFastmcp = /["']fastmcp["']/.test(content) || /["']fastmcp[><=]/.test(content);
187+
170188
// Try to extract version from pyproject.toml if present
171189
// Matches patterns like "mcp>=1.0.0" or "mcp==1.0.0"
172-
const versionMatch = content.match(/["']mcp[><=]=?\s*([^"',\]]+)["']/);
190+
const mcpVersionMatch = content.match(/["']mcp[><=]=?\s*([^"',\]]+)["']/);
191+
const fastmcpVersionMatch = content.match(/["']fastmcp[><=]=?\s*([^"',\]]+)["']/);
173192

193+
// Prioritize official SDK, but FastMCP is also a valid MCP framework
174194
if (hasMcp) {
175195
mcpSdkInfo = {
176196
detected: true,
177-
version: versionMatch?.[1],
197+
version: mcpVersionMatch?.[1],
178198
package: 'mcp',
179199
runtime: 'python'
180200
};
201+
} else if (hasFastmcp) {
202+
mcpSdkInfo = {
203+
detected: true,
204+
version: fastmcpVersionMatch?.[1],
205+
package: 'fastmcp',
206+
runtime: 'python'
207+
};
181208
}
182209
}
183210

services/backend/src/routes/teams/deploy/deploy.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -508,22 +508,32 @@ export default async function deployRoutes(server: FastifyInstance) {
508508
// Extract validated metadata
509509
const { metadata } = repoValidationResult;
510510
const commitSha = metadata!.commit_sha;
511-
const packageName = metadata!.name;
511+
let packageName = metadata!.name;
512512
const packageVersion = metadata!.version;
513513
const packageDescription = metadata!.description;
514514
const packageLicense = metadata!.license;
515515
const runtime = metadata!.runtime;
516516

517+
// Parse GitHub URL early (needed for fallback and server creation)
518+
const { owner, repo } = parseGitHubUrl(repository_url);
519+
520+
// Fallback: Generate package name from repository name if not present
521+
// Common for Python projects with only requirements.txt (no pyproject.toml)
522+
if (!packageName) {
523+
packageName = repo; // e.g., "mcp-test-fastmcp"
524+
request.log.info({
525+
generatedPackageName: packageName,
526+
source: 'repository_name'
527+
}, 'Generated package name from repository (no pyproject.toml)');
528+
}
529+
517530
request.log.info({
518531
packageName,
519532
version: packageVersion,
520533
runtime,
521534
mcpSdkDetected: metadata!.mcp_sdk.detected
522535
}, 'Repository validated successfully');
523536

524-
// Parse GitHub URL for owner/repo (needed for server creation)
525-
const { owner, repo } = parseGitHubUrl(repository_url);
526-
527537
// ============================================
528538
// STEP 7: Create mcpServers Entry
529539
// ============================================

0 commit comments

Comments
 (0)