File size: 2,114 Bytes
14fdc5e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
from __future__ import annotations

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastmcp import FastMCP
from mcp.server.sse import SseServerTransport
from starlette.responses import Response
from starlette.applications import Starlette
import uvicorn
from starlette.routing import Mount, Route

from core.config import get_settings
from mcp_server.router import register_tools

settings = get_settings()

mcp = FastMCP("RecruitmentMCP")
register_tools(mcp)

transport = SseServerTransport("/messages/")


async def sse_endpoint(request):
    async with transport.connect_sse(request.scope, request.receive, request._send) as streams:
        await mcp._mcp_server.run(
            streams[0],
            streams[1],
            mcp._mcp_server.create_initialization_options(),
        )
    # Return a concrete response after client disconnect to avoid NoneType route errors.
    return Response(status_code=204)


mcp_app = Starlette(
    routes=[
        Route("/sse", endpoint=sse_endpoint),
        Mount("/messages/", app=transport.handle_post_message),
    ]
)

app = FastAPI(title="Recruitment MCP Server")
app.mount("/mcp-server", mcp_app)

for target in (app, mcp_app):
    target.add_middleware(
        CORSMiddleware,
        allow_origins=settings.cors_origin_list,
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )


@app.get("/mcp-health")
def mcp_health() -> dict:
    return {
        "ok": True,
        "mcp_endpoint": "/mcp-server/sse",
        "tools": [
            "ingest_resume_pdf",
            "semantic_candidate_search",
            "candidate_metadata_query",
            "compute_job_match_score",
            "get_policy_info",
            "manage_application_status",
            "manage_interview_records",
            "generate_job_posting",
            "bulk_ingest_reference_resumes",
        ],
    }


if __name__ == "__main__":
    uvicorn.run("mcp_server.server:app", host=settings.host, port=9000, reload=False)