Skip to main content
Glama
krollchristensen

Sample Server

MCP-demo med Python, FastMCP, Claude Desktop og Cursor

Dette repo viser et simpelt eksempel på en lokal MCP-server skrevet i Python med FastMCP.

Eksemplet udstiller tre MCP-tools:

get_weather
calculate
convert_currency

Formålet er at vise, hvordan en AI-applikation som Claude Desktop eller Cursor kan bruge eksterne funktioner gennem MCP.

Kort forklaring

MCP står for Model Context Protocol.

I dette eksempel er rollerne:

Rolle

I dette eksempel

MCP host

Claude Desktop eller Cursor

MCP client

Den interne MCP-forbindelse i Claude/Cursor

MCP server

Python-programmet server.py

Tools

Funktionerne get_weather, calculate og convert_currency

Claude Desktop og Cursor starter Python-programmet som en lokal MCP-server. Serveren kører via stdio, så den kommunikerer gennem standard input/output i stedet for HTTP.

Related MCP server: Weather MCP Server

Hvorfor er eksemplet relevant?

Eksemplet viser, at MCP ikke bare handler om at kalde en funktion. Det handler om at standardisere forbindelsen mellem AI-applikationer og eksterne capabilities.

I stedet for at hver AI-app skal specialintegreres med hvert værktøj, kan værktøjer udstilles som MCP-servere.

Det giver en mere modulær arkitektur:

AI-applikation
      |
   MCP client
      |
   MCP server
      |
 Lokale tools, filer, API'er eller databaser

Projektstruktur

MCP_Test/
├── server.py
├── pyproject.toml
├── uv.lock
└── .venv/

Forudsætninger

Du skal have installeret:

Python
uv
Claude Desktop og/eller Cursor

Tjek at uv virker:

uv --version

Find eventuelt den fulde sti til uv:

where.exe uv

Eksempel:

C:\Users\mikc\.local\bin\uv.exe

Opret projektet

Stå i projektmappen:

cd C:\Users\mikc\IdeaProjects\MCP_Test

Hvis projektet ikke allerede har en pyproject.toml, så kør:

uv init --bare

Installer FastMCP:

uv add fastmcp

server.py

Gem denne fil som:

C:\Users\mikc\IdeaProjects\MCP_Test\server.py
from fastmcp import FastMCP

# MCP-serveren er den del, der udstiller capabilities til en AI-applikation.
#
# I dette eksempel er rollerne:
# - Claude Desktop eller Cursor = MCP host
# - Deres interne forbindelse til denne proces = MCP client
# - Dette Python-program = MCP server
#
# Navnet "Sample Server" vises i hosten, så brug et navn der er let at genkende.
mcp = FastMCP("Sample Server")


# @mcp.tool() gør funktionen til en MCP capability af typen tool.
#
# Et tool er en handling eller funktion, som AI'en kan kalde.
#
# Discovery:
# Hosten kan opdage tool-navn, parametre og docstring.
# Derfor er tydelige funktionsnavne, simple parametre og gode docstrings vigtige.
@mcp.tool()
def get_weather(location: str) -> str:
    """Get the current weather for a specified location."""
    # Demo-tool:
    # Dette henter ikke rigtigt vejr fra et API.
    #
    # Det viser blot, hvordan et tool kan modtage input fra hosten
    # og returnere et resultat tilbage til AI'ens kontekst.
    return f"Weather in {location}: Sunny, 72°F"


# Et lille og afgrænset tool.
#
# Designpointen er:
# Lav hellere flere små tools end én stor funktion, der prøver at gøre alt.
@mcp.tool()
def calculate(expression: str) -> float | str:
    """Calculate the result of a mathematical expression."""
    try:
        # Kun til demo:
        # eval() bør ikke bruges i rigtig produktion,
        # fordi brugeren potentielt kan sende farlig kode.
        #
        # I undervisning er det dog et simpelt eksempel på:
        # prompt -> tool call -> execution -> resultat tilbage til hosten.
        return eval(expression)
    except Exception as e:
        # Fejlhåndtering er vigtig, fordi MCP-clienten skal kunne få
        # et klart svar tilbage, hvis execution fejler.
        return f"Error calculating expression: {str(e)}"


# Endnu et lille tool med tydelige parametre.
#
# AI'en kan se parameterlisten og bruge den til at kalde funktionen korrekt.
@mcp.tool()
def convert_currency(amount: float, from_currency: str, to_currency: str) -> str:
    """Convert amount from one currency to another."""
    # Demo-data:
    # I en rigtig MCP-server kunne dette være et kald til et eksternt API,
    # en database eller et internt system.
    #
    # Det viser pointen om, at MCP-serveren kan skjule kompleksitet
    # bag et simpelt tool-interface.
    rates = {
        "USD": 1.0,
        "EUR": 0.85,
        "GBP": 0.73,
        "JPY": 110.0,
        "INR": 83.0
    }

    if from_currency not in rates or to_currency not in rates:
        return f"Unsupported currency pair: {from_currency} to {to_currency}"

    converted = amount * (rates[to_currency] / rates[from_currency])
    return f"{amount} {from_currency} = {converted:.2f} {to_currency}"


# MCP lifecycle:
#
# FastMCP håndterer:
# - initialization
# - discovery
# - execution
# - termination
#
# Når Claude Desktop eller Cursor starter serveren,
# kommunikerer de med denne proces via stdio.
#
# mcp.run() uden argumenter bruger stdio som standard.
# Det passer derfor til både Claude Desktop og Cursor.
if __name__ == "__main__":
    mcp.run()

Test serveren lokalt

Kør:

cd C:\Users\mikc\IdeaProjects\MCP_Test
uv run server.py

Hvis terminalen bare står stille, er det normalt.

En stdio-MCP-server venter på, at en host, fx Claude Desktop eller Cursor, kommunikerer med den.

Stop serveren igen med:

Ctrl + C

Opsætning i Claude Desktop

Claude Desktop bruger filen:

C:\Users\mikc\AppData\Roaming\Claude\claude_desktop_config.json

Du kan åbne mappen med:

explorer $env:APPDATA\Claude

Hvis filen allerede findes, skal du ikke nødvendigvis slette indholdet. Du skal tilføje mcpServers på samme niveau som de andre hovedfelter.

Eksempel med fuld sti til uv:

{
  "mcpServers": {
    "sample_mcp": {
      "command": "C:\\Users\\mikc\\.local\\bin\\uv.exe",
      "args": [
        "--directory",
        "C:\\Users\\mikc\\IdeaProjects\\MCP_Test",
        "run",
        "server.py"
      ]
    }
  }
}

Hvis din fil allerede indeholder andet indhold, fx preferences, kan den se sådan her ud:

{
  "preferences": {
    "remoteToolsDeviceName": "z4020"
  },
  "coworkUserFilesPath": "C:\\Users\\mikc\\Claude",
  "mcpServers": {
    "sample_mcp": {
      "command": "C:\\Users\\mikc\\.local\\bin\\uv.exe",
      "args": [
        "--directory",
        "C:\\Users\\mikc\\IdeaProjects\\MCP_Test",
        "run",
        "server.py"
      ]
    }
  }
}

Vigtigt:

mcpServers skal ikke ligge inde i preferences.
mcpServers skal ligge på øverste niveau i JSON-filen.

Efter ændringer:

1. Gem filen
2. Luk Claude Desktop helt
3. Åbn Claude Desktop igen

Test i Claude Desktop

Skriv fx:

Brug get_weather med location Copenhagen

eller:

Brug calculate til at regne 12 * 8 + 4

eller:

Brug convert_currency til at konvertere 100 USD til EUR

Claude kan spørge om tilladelse til at bruge værktøjet. Godkend kaldet.

Opsætning i Cursor

Cursor bruger typisk denne fil:

C:\Users\mikc\.cursor\mcp.json

Du kan også finde opsætningen i Cursor under:

Settings / Customize
Tools & MCPs

Brug denne mcp.json:

{
  "mcpServers": {
    "sample_mcp": {
      "type": "stdio",
      "command": "C:\\Users\\mikc\\.local\\bin\\uv.exe",
      "args": [
        "--directory",
        "C:\\Users\\mikc\\IdeaProjects\\MCP_Test",
        "run",
        "server.py"
      ]
    }
  }
}

Gem filen.

Gå derefter til:

Settings / Customize
Tools & MCPs
Home MCP Servers
sample_mcp

Du bør kunne se disse tools:

get_weather
calculate
convert_currency

Test i Cursor

Åbn Cursor-chatten.

Brug ikke kun ren Ask-mode, hvis Cursor ikke vil kalde tools. Vælg i stedet en agent-/composer-tilstand, eller tilføj MCP-serveren via:

+ 
MCP Servers
sample_mcp

Test med:

Brug MCP-tool get_weather med location Copenhagen

eller:

Kald sample_mcp calculate med expression "12 * 8 + 4"

eller:

Kald sample_mcp convert_currency med amount 100, from_currency USD og to_currency EUR

Typiske fejl og løsninger

Fejl: uv findes ikke

Hvis Claude eller Cursor ikke kan finde uv, så find den fulde sti:

where.exe uv

Eksempel:

C:\Users\mikc\.local\bin\uv.exe

Brug derefter den fulde sti i configen:

"command": "C:\\Users\\mikc\\.local\\bin\\uv.exe"

Fejl: pyproject.toml mangler

Hvis du får:

No pyproject.toml found

så opret projektfilen:

uv init --bare

og installer FastMCP:

uv add fastmcp

Fejl: adgang nægtet til .venv

Hvis du får en fejl om adgang til .venv, så kan miljøet være låst af en terminal eller IDE.

Prøv:

deactivate
Remove-Item -Recurse -Force .venv
uv add fastmcp

Luk eventuelt Cursor, IntelliJ eller andre terminaler, der bruger projektet.

Fejl: den angivne sti blev ikke fundet

Tjek at projektmappen findes:

Test-Path C:\Users\mikc\IdeaProjects\MCP_Test

Tjek at server.py findes:

Test-Path C:\Users\mikc\IdeaProjects\MCP_Test\server.py

Begge skal give:

True

Ændringer i server.py slår ikke igennem

Hvis du ændrer i server.py, skal MCP-serveren genstartes.

I Claude Desktop:

Luk Claude helt og åbn igen

I Cursor:

Slå MCP-serveren fra og til igen

eller genstart Cursor.

Undervisningspointer

Dette eksempel kan bruges til at forklare flere centrale MCP-begreber.

Host, client og server

Claude Desktop og Cursor er hosts. De har en MCP-client indbygget, som taler med MCP-serveren.

Python-filen server.py er MCP-serveren.

Capabilities og tools

Funktionerne med @mcp.tool() bliver til capabilities af typen tools.

Tools får AI'en til at gøre noget, fx beregne, konvertere eller hente data.

Discovery

Claude og Cursor kan opdage, hvilke tools serveren tilbyder.

Derfor er dette vigtigt:

Gode funktionsnavne
Simple parametre
Klare docstrings

Execution

Når brugeren skriver en prompt, kan AI'en vælge et relevant tool.

Flowet er:

Bruger skriver prompt
AI vurderer behov for tool
MCP-client kalder MCP-server
Python-funktionen udføres
Resultatet sendes tilbage til AI'en
AI'en formulerer svaret

Små tools frem for ét stort tool

Dette eksempel har tre små tools:

get_weather
calculate
convert_currency

Det er bedre end én stor funktion, der prøver at gøre alt.

Små tools er lettere at forstå, teste, fejlfinde og genbruge.

Forslag til videreudvikling

Når grundeksemplet virker, kan man udvide med:

Read-only taskliste fra JSON-fil
Opslag i lokal SQLite-database
GitHub issue-helper
MongoDB read-only query
API-kald til rigtig vejrservice
Code review prompt

Start gerne med read-only eksempler, før der laves tools med sideeffekter som oprettelse, sletning eller afsendelse.

Afsluttende pointe

MCP gør AI til en del af en softwarearkitektur.

Det handler derfor ikke kun om at skrive gode prompts, men om at designe:

værktøjer
grænser
adgang
ansvar
fejlhåndtering
sikkerhed

Det gør MCP relevant for både programmering, systemudvikling, softwarearkitektur og IT-sikkerhed.

Available Tools

3 tools
calculateC

Calculate the result of a mathematical expression.

ParametersJSON Schema
NameRequiredDescriptionDefault
expressionYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

C2.8/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full burden. It only says 'calculate the result,' missing critical details like error handling, allowed complexity, security implications, or return format. The presence of an output schema (not shown) mitigates this slightly, but the description alone is insufficient.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence, making it concise, but it may be too minimal. Front-loading is fine, but the lack of structure (e.g., no separation of purpose, usage, behavior) hurts readability for the agent.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has one parameter, no annotations, and an output schema (unseen), the description should provide more context about return values, error cases, or supported math. It is incomplete for a tool that likely evaluates arbitrary expressions, which has safety and formatting implications.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It fails to explain the format of the 'expression' string (e.g., operators, functions, precedence). The agent has no guidance on how to construct valid expressions beyond the type 'string'.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool calculates a mathematical expression, which differentiates it from sibling tools like convert_currency or get_weather. However, it does not specify the scope of supported operations (e.g., basic arithmetic vs. advanced functions), leaving some ambiguity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance is given on when to use this tool versus alternatives, but the sibling tools are domain-specific (currency, weather), so the intended use case is reasonably implied. No exclusions or prerequisites are mentioned.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

convert_currencyC

Convert amount from one currency to another.

ParametersJSON Schema
NameRequiredDescriptionDefault
amountYes
to_currencyYes
from_currencyYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

C2.8/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden for behavioral disclosure. It does not mention whether the conversion uses real-time rates, historical data, or any required authentication. No behavioral traits beyond the basic function are disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single concise sentence, front-loaded with the core purpose. It wastes no words, though it could include more detail without losing conciseness. The structure is efficient for the information it conveys.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the three required parameters, absence of parameter descriptions, and no annotations, the description is inadequate. It does not address parameter format, behavior, or error handling. The existence of an output schema partially compensates for return values, but the description remains incomplete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has three parameters with 0% description coverage, and the description adds no meaning beyond the parameter names. It does not explain formats (e.g., currency codes), constraints, or examples, leaving the agent without guidance on valid values.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Convert amount from one currency to another,' specifying the verb 'convert' and the resource 'amount' with source and target currencies. It distinguishes from sibling tools 'calculate' (arithmetic) and 'get_weather' (weather data).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives, nor any constraints or prerequisites. It only states the basic function, leaving the agent without context for selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_weatherC

Get the current weather for a specified location.

ParametersJSON Schema
NameRequiredDescriptionDefault
locationYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

C2.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must convey behavioral traits. It only states 'get the current weather' with no disclosure about data freshness, API limits, caching, or required authentication. A 2 indicates minimal transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that directly states the tool's purpose. No extraneous content, perfectly front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (1 parameter) and presence of an output schema, the description should at least hint at what the output contains. It does not, nor does it address any other contextual signals like rate limits or location validation. A 2 reflects significant incompleteness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The sole parameter 'location' has a 0% schema description coverage, and the tool description only says 'specified location' without any added detail about format, accepted values, or examples. The description fails to compensate for the missing schema documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('get') and the resource ('current weather') with a location parameter. However, it does not provide any differentiation from sibling tools (calculate, convert_currency), though these are unrelated, so no strong need for discrimination. A 4 reflects clear but basic purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description offers no guidance on when to use this tool versus alternatives, no prerequisites, and no exclusions. With sibling tools in different domains, the lack of usage context is acceptable but still missing explicit advice.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 3 tool updatesv0.1.0
    • First observedcalculate
    • First observedconvert_currency
    • First observedget_weather

TDQS

B3.2/5.0
Disambiguation5/5

Each tool targets a completely different task (mathematical calculation, currency conversion, and weather retrieval), so there is no ambiguity in purpose.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern (calculate, convert_currency, get_weather), making them predictable and easy to understand.

Tool Count4/5

Three tools is a reasonable number for a utility server, though the set feels slightly sparse for a general-purpose toolkit.

Completeness2/5

The tools form a disjoint set with no clear domain; they cover only a few random utilities, leaving obvious gaps for a general-purpose server.

Maintenance

ActivityStale
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    D
    maintenance
    Demonstrates creating and connecting an MCP weather server using FastMCP, with support for integration with Claude Desktop, Cursor, and local LLMs to query weather alerts and information.
    1
    1
    -
  • F
    license
    B
    quality
    D
    maintenance
    A basic MCP server adapted from the official quickstart guide that provides weather data functionality and works with OpenAI chat completions API. Demonstrates MCP server setup with configuration examples for Claude Desktop and development tools.
    2
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    A MCP server for querying real-time weather information for any city worldwide using the free Open-Meteo API, supporting CLI and integration with AI clients like Claude and Cursor.
    22
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/krollchristensen/MCP_Test'

If you have feedback or need assistance with the MCP directory API, please join our Discord server