Podlings MCP
A small dependency-free MCP server for working with Apache Software Foundation Incubator podlings.xml data.
It exposes tools to:
- load podling metadata from a URL or local XML file
- list podlings with optional filtering
- list current, graduated, and retired podlings
- fetch details for a specific podling
- return basic Incubator summary statistics
- return mentor-count coverage statistics
- analyze podling starts and active population over time
- analyze yearly completion counts
- analyze graduation rate over time
- analyze graduation and retirement duration over time
If source is omitted, the server defaults to https://incubator.apache.org/podlings.xml.
The default ASF podlings XML source is cached locally for 24 hours. Set PODLINGS_MCP_CACHE_DIR to override the cache directory.
Requirements
- Python 3.12+
Run
python3 server.py
The server uses stdio, so it is intended to be launched by an MCP client.
Test
python3 -m unittest discover -s tests -v
The tests cover parser behavior, tool functions, error cases, and a small end-to-end MCP stdio exchange.
Developer Commands
make format
make check-format
make test
make coverage
make lint
make typecheck
make check
Formatting and linting use ruff, including make check-format for CI-style format verification, and type checking uses mypy. See docs/architecture.md for the current module layout.
Example MCP client config
{
"mcpServers": {
"podlings": {
"command": "python3",
"args": ["/Users/yourname/PodlingsMCP/server.py"]
}
}
}
Concepts and Defaults
sponsor_typedefaults toincubatoracross the filtering and analytics tools.completedmeans podlings that reached an end state:graduatedorretired.- Count and rate timeline tools use podling
enddateto place outcomes into a year. - Duration timeline tools use both
startdateandenddateto calculate months to graduate or retire. completed_podlings_by_yearreturns both lists by default, and thegraduated_podlings_by_yearandretired_podlings_by_yeartools are convenience wrappers over that same lookup.
Tools
list_podlings
List podlings from podlings.xml.
Arguments:
source: URL or local file pathstatus: optional exact status filtersponsor_type: optional sponsor type filter, defaults toincubatorsearch: optional case-insensitive name/description/champion searchlimit: optional max number of results to return
source is optional and defaults to the ASF Incubator podlings.xml URL.
list_current_podlings
List podlings with status="current".
Arguments:
source: URL or local file pathsponsor_type: optional sponsor type filter, defaults toincubatorsearch: optional case-insensitive name/description/champion searchlimit: optional max number of results to return
source is optional and defaults to the ASF Incubator podlings.xml URL.
list_graduated_podlings
List podlings with status="graduated".
Arguments:
source: URL or local file pathsponsor_type: optional sponsor type filter, defaults toincubatorsearch: optional case-insensitive name/description/champion searchlimit: optional max number of results to return
source is optional and defaults to the ASF Incubator podlings.xml URL.
list_retired_podlings
List podlings with status="retired".
Arguments:
source: URL or local file pathsponsor_type: optional sponsor type filter, defaults toincubatorsearch: optional case-insensitive name/description/champion searchlimit: optional max number of results to return
source is optional and defaults to the ASF Incubator podlings.xml URL.
get_podling
Return a single podling by name.
Arguments:
source: URL or local file pathname: podling name
source is optional and defaults to the ASF Incubator podlings.xml URL.
podling_stats
Return summary statistics for a podlings.xml source.
Arguments:
source: URL or local file pathsponsor_type: optional sponsor type filter, defaults toincubator
source is optional and defaults to the ASF Incubator podlings.xml URL.
The stats include sponsor classification so you can distinguish:
incubator: sponsored by the Incubatorproject: sponsored by another ASF project/PMCunknown: no sponsor value was found
mentor_count_stats
Return mentor coverage and mentor-count distribution stats for a podlings.xml source.
Arguments:
source: URL or local file pathsponsor_type: optional sponsor type filter, defaults toincubator
source is optional and defaults to the ASF Incubator podlings.xml URL.
raw_podlings_xml_info
Return source metadata and a small preview of parsed records for troubleshooting.
Arguments:
source: URL or local file path
source is optional and defaults to the ASF Incubator podlings.xml URL.
graduation_rate_over_time
Return yearly graduation and retirement counts plus graduation rate based on podling enddate.
Arguments:
source: URL or local file pathstart_year: optional inclusive start year filterend_year: optional inclusive end year filtersponsor_type: optional sponsor type filter, defaults toincubator
source is optional and defaults to the ASF Incubator podlings.xml URL.
podlings_started_over_time
Return yearly podling start counts based on startdate.
Arguments:
source: URL or local file pathstart_year: optional inclusive start year filterend_year: optional inclusive end year filtersponsor_type: optional sponsor type filter, defaults toincubator
source is optional and defaults to the ASF Incubator podlings.xml URL.
started_podlings_by_year
Return the podlings that started in a specific year.
Arguments:
source: URL or local file pathyear: required year to inspectsponsor_type: optional sponsor type filter, defaults toincubator
source is optional and defaults to the ASF Incubator podlings.xml URL.
active_podlings_by_year
Return yearly active-podling counts based on lifecycle span.
Arguments:
source: URL or local file pathstart_year: optional inclusive start year filterend_year: optional inclusive end year filtersponsor_type: optional sponsor type filter, defaults toincubator
source is optional and defaults to the ASF Incubator podlings.xml URL.
active_podlings_in_year
Return the podlings that were active during a specific year.
Arguments:
source: URL or local file pathyear: required year to inspectsponsor_type: optional sponsor type filter, defaults toincubator
source is optional and defaults to the ASF Incubator podlings.xml URL.
completion_rate_over_time
Return yearly completion rate using completed outcomes divided by active population.
Arguments:
source: URL or local file pathstart_year: optional inclusive start year filterend_year: optional inclusive end year filtersponsor_type: optional sponsor type filter, defaults toincubator
source is optional and defaults to the ASF Incubator podlings.xml URL.
completion_count_over_time
Return yearly completed podling counts based on enddate, split into graduated and retired outcomes.
Arguments:
source: URL or local file pathstart_year: optional inclusive start year filterend_year: optional inclusive end year filtersponsor_type: optional sponsor type filter, defaults toincubator
source is optional and defaults to the ASF Incubator podlings.xml URL.
completed_podlings_by_year
Return the podlings that completed in a specific year, split into graduated and retired outcomes.
Arguments:
source: URL or local file pathyear: required year to inspectstatus: optional filter,graduatedorretiredsponsor_type: optional sponsor type filter, defaults toincubator
source is optional and defaults to the ASF Incubator podlings.xml URL.
completed_podlings_in_range
Return the podlings that completed within an inclusive year range.
Arguments:
source: URL or local file pathstart_year: required inclusive start yearend_year: required inclusive end yearstatus: optional filter,graduatedorretiredsponsor_type: optional sponsor type filter, defaults toincubator
source is optional and defaults to the ASF Incubator podlings.xml URL.
graduated_podlings_by_year
Return the podlings that graduated in a specific year.
Arguments:
source: URL or local file pathyear: required year to inspectsponsor_type: optional sponsor type filter, defaults toincubator
source is optional and defaults to the ASF Incubator podlings.xml URL.
retired_podlings_by_year
Return the podlings that retired in a specific year.
Arguments:
source: URL or local file pathyear: required year to inspectsponsor_type: optional sponsor type filter, defaults toincubator
source is optional and defaults to the ASF Incubator podlings.xml URL.
graduation_time_over_time
Return yearly time-to-graduate stats in months based on podling startdate and enddate, including average, median, and percentile views.
Arguments:
source: URL or local file pathstart_year: optional inclusive start year filterend_year: optional inclusive end year filtersponsor_type: optional sponsor type filter, defaults toincubator
source is optional and defaults to the ASF Incubator podlings.xml URL.
time_to_retirement_over_time
Return yearly time-to-retirement stats in months based on podling startdate and enddate, including average, median, and percentile views.
Arguments:
source: URL or local file pathstart_year: optional inclusive start year filterend_year: optional inclusive end year filtersponsor_type: optional sponsor type filter, defaults toincubator
source is optional and defaults to the ASF Incubator podlings.xml URL.
Examples
List current incubator-sponsored podlings:
{
"name": "list_current_podlings",
"arguments": {}
}
Typical response:
{
"returned": 1,
"total_matching": 1,
"podlings": [
{
"name": "ExampleOne",
"status": "current",
"sponsor_type": "incubator"
}
]
}
Analyze graduation timing for project-sponsored podlings:
{
"name": "graduation_time_over_time",
"arguments": {
"sponsor_type": "project"
}
}
Analyze yearly completion counts for project-sponsored podlings:
{
"name": "completion_count_over_time",
"arguments": {
"sponsor_type": "project"
}
}
Typical response:
{
"years": [
{
"year": 2024,
"graduated": 1,
"retired": 0,
"completed": 1
}
],
"overall_completed": 1,
"overall_graduated": 1,
"overall_retired": 0
}
Analyze yearly start counts for incubator-sponsored podlings:
{
"name": "podlings_started_over_time",
"arguments": {}
}
Typical response:
{
"years": [
{
"year": 2022,
"started": 1
},
{
"year": 2025,
"started": 1
}
],
"overall_started": 2
}
Look up which podlings were active in a specific year:
{
"name": "active_podlings_in_year",
"arguments": {
"year": 2023
}
}
Typical response:
{
"year": 2023,
"active": ["ExampleThree"],
"active_count": 1
}
Look up which podlings completed in a specific year:
{
"name": "completed_podlings_by_year",
"arguments": {
"year": 2024,
"sponsor_type": "project"
}
}
Typical response:
{
"year": 2024,
"status_filter": "all",
"graduated": ["ExampleTwo"],
"retired": [],
"completed": ["ExampleTwo"],
"completed_count": 1
}
Look up which podlings completed in a year range:
{
"name": "completed_podlings_in_range",
"arguments": {
"start_year": 2023,
"end_year": 2024
}
}
Typical response:
{
"start_year": 2023,
"end_year": 2024,
"status_filter": "all",
"graduated": [],
"retired": ["ExampleThree"],
"completed": ["ExampleThree"],
"completed_count": 1
}
Look up just the podlings that retired in a specific year:
{
"name": "retired_podlings_by_year",
"arguments": {
"year": 2023
}
}
Typical response:
{
"year": 2023,
"status_filter": "retired",
"graduated": [],
"retired": ["ExampleThree"],
"completed": ["ExampleThree"],
"completed_count": 1
}
Look up just the podlings that graduated in a specific year:
{
"name": "graduated_podlings_by_year",
"arguments": {
"year": 2024,
"sponsor_type": "project"
}
}
Typical response:
{
"year": 2024,
"status_filter": "graduated",
"graduated": ["ExampleTwo"],
"retired": [],
"completed": ["ExampleTwo"],
"completed_count": 1
}
Typical response:
{
"years": [
{
"year": 2024,
"graduated": 1,
"total_months_to_graduate": 17,
"average_months_to_graduate": 17.0,
"median_months_to_graduate": 17.0,
"p75_months_to_graduate": 17.0,
"p90_months_to_graduate": 17.0
}
],
"overall_graduated": 1,
"overall_average_months_to_graduate": 17.0
}
Analyze retirement timing for incubator-sponsored podlings after 2020:
{
"name": "time_to_retirement_over_time",
"arguments": {
"start_year": 2021
}
}
Typical response:
{
"years": [
{
"year": 2023,
"retired": 1,
"total_months_to_retire": 16,
"average_months_to_retire": 16.0,
"median_months_to_retire": 16.0,
"p75_months_to_retire": 16.0,
"p90_months_to_retire": 16.0
}
],
"overall_retired": 1,
"overall_average_months_to_retire": 16.0
}
Source examples
- ASF URL:
https://incubator.apache.org/podlings.xml - Local file:
/path/to/podlings.xml
Notes
- Remote sources are fetched with Python's standard library.
- XML parsing targets the ASF Incubator
podlings.xmlstructure directly. - Tools that accept
sponsor_typedefault toincubator. - Valid
sponsor_typevalues areincubator,project, andunknown.