foss42 MCP Server
OfficialClick on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@foss42 MCP ServerWhat's the population and flag of Germany?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
foss42 MCP Server
An MCP server exposing the foss42 utilities — country data, text and case conversion, and human-friendly number and date formatting.
Built with FastMCP. 5 workflow-shaped tools, no API key, no network calls — everything runs locally against bundled data.
See DESIGN.md for the reasoning and measured before/after.
Quick start
Requires Python 3.10+.
python3 -m venv .venv
.venv/bin/pip install -r requirements.txtRun over stdio (the default, for local clients such as Claude Code or Claude Desktop):
.venv/bin/python server.pyOr over streamable HTTP, for a remotely reachable server:
.venv/bin/python server.py --transport http --host 0.0.0.0 --port 8000The MCP endpoint is then http://<host>:<port>/mcp.
Flag | Default | Description |
|
|
|
|
| Bind address (http only) |
|
| Bind port (http only) |
To try the tools by hand, see TESTING.md.
Related MCP server: CountryCallingCodes
Connecting a client
Claude Code
claude mcp add foss42 -- /path/to/mcp/.venv/bin/python /path/to/mcp/server.pyClaude Desktop — add to claude_desktop_config.json:
{
"mcpServers": {
"foss42": {
"command": "/path/to/mcp/.venv/bin/python",
"args": ["/path/to/mcp/server.py"]
}
}
}Use absolute paths, and point at the venv's interpreter rather than a bare python.
All five tools are annotated readOnlyHint, idempotentHint, destructiveHint: false and
openWorldHint: false, so clients can skip confirmation prompts.
Tools
get_country_info
Look up one or more countries and return only the fields you ask for.
get_country_info(country: str | list[str], include: list[CountryField] = None)country takes a name, alias, or ISO alpha-2/alpha-3 code. You never need to know the
code. Pass a list to look up several at once.
Resolution is forgiving: diacritics, punctuation and the definite article are normalised
(Türkiye, Turkiye, U.S.A., The Netherlands), historical and colloquial names resolve
(Burma → Myanmar, Swaziland → Eswatini, Holland → Netherlands, Great Britain → GB),
and an ambiguous input is reported rather than guessed:
"Korea" → 'Korea' matches more than one country: North Korea (KP), South Korea (KR).
Pass the one you mean, or use search_countries to compare them.include selects fields; the default is names, codes, flag, stats.
Field | Contents |
| Common name, official name, known aliases |
| ISO 3166-1 alpha-2 and alpha-3 |
| Flag emoji |
| International dialing code, e.g. |
| Area, population, female population percent (World Bank) |
| Continent and UN subregion |
| States/provinces with code, name, category |
Subdivision data exists for 11 countries: AE, AU, CA, CH, CN, ES, IN, JP, KR, SG, US. The tool says so rather than making you find out by failing.
// get_country_info("UK", include=["flag", "stats", "phone"])
{
"country": "United Kingdom", "alpha2": "GB", "flag": "🇬🇧",
"intl_phone_code": "+44",
"stats": { "area": 243610.0, "population": 67326569, "population_female_percent": 50.58 }
}search_countries
Find countries by partial name or region when you don't know the exact name.
search_countries(query: str = None, region: str = None, limit: int = 25)Regions are the 5 continents (Africa, Americas, Asia, Europe, Oceania) plus UN
subregions such as South America, Western Europe, Southern Asia, Caribbean — 30 in
total. Returns {matches, total, shown} and a note when truncated.
transform_text
Convert text between naming conventions and other styles.
transform_text(text: str | list[str], style: TextStyle, separator: str = "-")Pass a list to convert many strings in one call. Identifier styles normalise _, -, .,
spaces and camelCase boundaries first, so user_id, user-id, user id and userId all
give the same result, and XMLHttpRequest → xml_http_request.
Using Grass is green as input:
Style | Result | Style | Result |
| grass is green |
| GRASS_IS_GREEN |
| GRASS IS GREEN |
| grass_Is_Green |
| Grass Is Green |
| Grass_Is_Green |
| Grass Is Green |
| grass.is.green |
| Grass is green |
| grass-is-green |
| gRASS IS GREEN |
| GRASS-IS-GREEN |
| grassisgreen |
| Grass-Is-Green |
| GRASSISGREEN |
| grass-is-green |
| GrassIsGreen |
| grassIsGreen |
| grass_is_green |
Reverse styles turn an identifier into words: camel_to_words, snake_to_words,
kebab_to_words. Also phone_to_numeric (1-800-FLOWERS → 1-800-3569377) and the
novelty styles leet, upside_down, mirror.
humanize_number
humanize_number(value: int | list[int], style: "bytes" | "social" | "rank", ...)Style | Example |
|
|
|
|
|
|
digits and add_space default per style, so the common case needs only value and style.
Pass a list to format a whole column in one call.
humanize_time
humanize_time(dt: str, dt_ref: str = None, fmt: str = None, units: "FULL" | "SHORT" = "FULL", ...)2020-12-27T18:31:29 → 5 years ago (with add_adverb=true).
Errors
Tools raise ToolError, so failures reach the client as readable, actionable messages:
// get_country_info(country="Germny")
{
"content": [{ "type": "text", "text":
"No country matches 'Germny'. Closest matches: Germany (DE), Guernsey (GG). Pass one of those, or use search_countries to browse." }],
"isError": true
}Invalid input is caught in two places: pydantic rejects anything violating the input schema
(a negative value, an unknown style) before the tool body runs, and src/errors.py
translates foss42's exceptions into messages that name the fix.
Development
.venv/bin/pip install -r requirements-dev.txt
.venv/bin/python -m pytestTests drive the server in-process via fastmcp.Client(mcp) — no subprocess, no network. See
TESTING.md for manual testing with the MCP Inspector, DESIGN.md
for why the tool surface looks like this, and CONTRIBUTING.md for how
to add a tool.
Layout
server.py entrypoint and transport selection
src/mcp_app.py the FastMCP instance
src/countries.py country name/alias/code resolution and data assembly
src/enums.py TextStyle, CountryField, HumanizeStyle, SystemEnum, DateUnitsEnum
src/errors.py foss42 exceptions -> ToolError
src/tools/ country, humanize, text
tests/ pytest suite using the in-memory clientTool logic lives in foss42/foss42-core; this repo is the MCP layer over it. Data and algorithm changes belong upstream.
License
Apache 2.0 — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Countries, timezones, elements, constants, HTTP status codes, unit conversion, and MIME type lookup.
iso-codes MCP — lookups against the Debian iso-codes project JSON.
CountryStateCity MCP — wraps CountryStateCity API (api.countrystatecity.in/v1)
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceMCP Server that gives AI assistants access to comprehensive country data from 250+ countries.1MIT
- AlicenseNot gradedqualityCmaintenanceFormat, validate and normalize international phone numbers, work out exactly how to dial one country from another, clean phone columns in CRM or contact exports, and find calling windows across time zones — using the countrycalling.codes API and MCP server.MIT
- AlicenseNot gradedqualityAmaintenanceProvides complete world location data (countries, states, cities) as an MCP server for AI assistants, enabling search and retrieval of geographic information through 11 tools and 5 resources.182 npm2MIT
- AlicenseAqualityCmaintenanceMCP server for the loc8n Geographic Data API. Exposes U.S. demographics, housing, mortgage, migration, employment, and geographic data as tools.2351 npmMIT