|
| 1 | +""" |
| 2 | +Minimal-but-solid MCP server with JWT hardening and sane defaults. |
| 3 | +
|
| 4 | +- Safe defaults for transports |
| 5 | +""" |
| 6 | + |
| 7 | +from fastmcp import FastMCP |
| 8 | + |
| 9 | +# to verify the JWT token |
| 10 | +# if you don't need to add security, you can remove this |
| 11 | +# in newer version of FastMCP should be replaced with |
| 12 | +# from fastmcp.server.auth.providers.jwt import JWTVerifier |
| 13 | +from fastmcp.server.auth import BearerAuthProvider |
| 14 | + |
| 15 | +from config import ( |
| 16 | + # first four needed only to manage JWT |
| 17 | + ENABLE_JWT_TOKEN, |
| 18 | + IAM_BASE_URL, |
| 19 | + ISSUER, |
| 20 | + AUDIENCE, |
| 21 | + TRANSPORT, |
| 22 | + # needed only if transport is stremable-http |
| 23 | + HOST, |
| 24 | + PORT, |
| 25 | +) |
| 26 | + |
| 27 | + |
| 28 | +# |
| 29 | +# if you don't need to add security, you can remove this part and set |
| 30 | +# AUTH = None, simply set ENABLE_JWT_TOKEN = False |
| 31 | +# |
| 32 | +AUTH = None |
| 33 | + |
| 34 | +if ENABLE_JWT_TOKEN: |
| 35 | + # check that a valid JWT token is provided |
| 36 | + AUTH = BearerAuthProvider( |
| 37 | + # this is the url to get the public key from IAM |
| 38 | + # the PK is used to check the JWT |
| 39 | + jwks_uri=f"{IAM_BASE_URL}/admin/v1/SigningCert/jwk", |
| 40 | + issuer=ISSUER, |
| 41 | + audience=AUDIENCE, |
| 42 | + ) |
| 43 | + |
| 44 | +# |
| 45 | +# define the MCP server |
| 46 | +# |
| 47 | +mcp = FastMCP("MCP server with few lines of code, but secure", auth=AUTH) |
| 48 | + |
| 49 | + |
| 50 | +# |
| 51 | +# MCP tools definition |
| 52 | +# add and write the code for the tools here |
| 53 | +# |
| 54 | +@mcp.tool |
| 55 | +def say_the_truth(user: str) -> str: |
| 56 | + """ |
| 57 | + This tool, given the name of the user return one of the secret truths. |
| 58 | +
|
| 59 | + Args: |
| 60 | + user: The caller's display name or identifier. |
| 61 | +
|
| 62 | + Returns: |
| 63 | + A short truth string. |
| 64 | + """ |
| 65 | + # here you'll put the code that reads and return the info requested |
| 66 | + # mark each tool with the annotation |
| 67 | + return f"{user}: Less is more!" |
| 68 | + |
| 69 | + |
| 70 | +# |
| 71 | +# Run the MCP server |
| 72 | +# |
| 73 | +if __name__ == "__main__": |
| 74 | + # Validate transport |
| 75 | + if TRANSPORT not in {"stdio", "streamable-http"}: |
| 76 | + # don't use sse! it is deprecated! |
| 77 | + raise RuntimeError(f"Unsupported TRANSPORT: {TRANSPORT}") |
| 78 | + |
| 79 | + if TRANSPORT == "stdio": |
| 80 | + # stdio doesn’t support host/port args |
| 81 | + mcp.run(transport=TRANSPORT) |
| 82 | + else: |
| 83 | + # For http/streamable-http transport, host/port are valid |
| 84 | + mcp.run( |
| 85 | + transport=TRANSPORT, |
| 86 | + host=HOST, |
| 87 | + port=PORT, |
| 88 | + ) |
0 commit comments