Skip to content

Conversation

AdvitXAtlan
Copy link
Contributor

@AdvitXAtlan AdvitXAtlan commented Sep 8, 2025

Model Context Protocol (MCP) Integration for Application SDK

Summary

This PR adds comprehensive Model Context Protocol (MCP) support to the Atlan Application SDK.

Core Features:

  • Added @mcp_tool decorator for marking activities as MCP tools
  • Added MCPServer class that auto-discovers decorated activities
  • Enhanced BaseApplication with enable_mcp parameter and automatic MCP mounting
  • Added mcp optional dependency group with FastMCP 2.0 integration
  • Support for streamable HTTP transport for AI agent communication

Architecture:

  • Activities marked with @mcp_tool are automatically exposed as AI tools
  • MCPServer reuses existing activity discovery logic from workflows
  • Clean integration: apps just add decorators + enable_mcp=True
  • FastMCP server automatically mounts on FastAPI at /mcp endpoint
  • No manual MCP server code needed in individual apps
  • Proper lifespan management for ASGI app mounting

Migration Guide

For existing applications wanting to add MCP support:

  1. Install MCP dependencies:

    pip install "atlan-application-sdk[mcp]"
  2. Decorate activities:

    from application_sdk.decorators.mcp_tool import mcp_tool
    
    @activity.defn
    @mcp_tool(description="Your activity description")
    async def your_activity(self, param: str) -> str:
        # existing code unchanged
  3. Enable MCP in application:

    app = BaseApplication(name="your-app", enable_mcp=True)
    # or via environment variable: ENABLE_MCP=true

Changelog

  • BREAKING: Added new optional dependency fastmcp>=2.0.0 in [mcp] extra
  • FEAT: Added @mcp_tool decorator in application_sdk.decorators.mcp_tool
  • FEAT: Added MCPServer class in application_sdk.servers.mcp.server
  • FEAT: Enhanced BaseApplication with enable_mcp parameter
  • FEAT: Automatic MCP server mounting on FastAPI at /mcp endpoint
  • REFACTOR: Moved MCP files to proper SDK directory structure

Additional context (e.g. screenshots, logs, links)

  • to be added

Checklist

  • Additional tests added
  • All CI checks passed
  • Relevant documentation updated

Copyleft License Compliance

  • Have you used any code that is subject to a Copyleft license (e.g., GPL, AGPL, LGPL)?
  • If yes, have you modified the code in the context of this project? please share additional details.

Copy link

github-actions bot commented Sep 8, 2025

📜 Docstring Coverage Report

RESULT: PASSED (minimum: 30.0%, actual: 75.8%)

Detailed Coverage Report
======= Coverage for /home/runner/work/application-sdk/application-sdk/ ========
----------------------------------- Summary ------------------------------------
| Name                                                                              | Total | Miss | Cover | Cover% |
|-----------------------------------------------------------------------------------|-------|------|-------|--------|
| application_sdk/__init__.py                                                       |     1 |    0 |     1 |   100% |
| application_sdk/constants.py                                                      |     1 |    0 |     1 |   100% |
| application_sdk/version.py                                                        |     1 |    0 |     1 |   100% |
| application_sdk/worker.py                                                         |     4 |    0 |     4 |   100% |
| application_sdk/activities/__init__.py                                            |     9 |    0 |     9 |   100% |
| application_sdk/activities/lock_management.py                                     |     3 |    0 |     3 |   100% |
| application_sdk/activities/common/__init__.py                                     |     1 |    1 |     0 |     0% |
| application_sdk/activities/common/models.py                                       |     2 |    0 |     2 |   100% |
| application_sdk/activities/common/utils.py                                        |     8 |    1 |     7 |    88% |
| application_sdk/activities/metadata_extraction/__init__.py                        |     1 |    1 |     0 |     0% |
| application_sdk/activities/metadata_extraction/base.py                            |     5 |    1 |     4 |    80% |
| application_sdk/activities/metadata_extraction/rest.py                            |     1 |    1 |     0 |     0% |
| application_sdk/activities/metadata_extraction/sql.py                             |    27 |    7 |    20 |    74% |
| application_sdk/activities/query_extraction/__init__.py                           |     1 |    1 |     0 |     0% |
| application_sdk/activities/query_extraction/sql.py                                |    13 |    1 |    12 |    92% |
| application_sdk/application/__init__.py                                           |    11 |    3 |     8 |    73% |
| application_sdk/application/metadata_extraction/sql.py                            |     7 |    1 |     6 |    86% |
| application_sdk/clients/__init__.py                                               |     4 |    0 |     4 |   100% |
| application_sdk/clients/atlan.py                                                  |     5 |    3 |     2 |    40% |
| application_sdk/clients/atlan_auth.py                                             |    10 |    0 |    10 |   100% |
| application_sdk/clients/base.py                                                   |     6 |    1 |     5 |    83% |
| application_sdk/clients/models.py                                                 |     3 |    0 |     3 |   100% |
| application_sdk/clients/redis.py                                                  |    27 |    0 |    27 |   100% |
| application_sdk/clients/sql.py                                                    |    16 |    0 |    16 |   100% |
| application_sdk/clients/temporal.py                                               |    13 |    1 |    12 |    92% |
| application_sdk/clients/utils.py                                                  |     2 |    1 |     1 |    50% |
| application_sdk/clients/workflow.py                                               |     9 |    2 |     7 |    78% |
| application_sdk/common/__init__.py                                                |     1 |    1 |     0 |     0% |
| application_sdk/common/aws_utils.py                                               |    10 |    1 |     9 |    90% |
| application_sdk/common/dapr_utils.py                                              |     2 |    1 |     1 |    50% |
| application_sdk/common/dataframe_utils.py                                         |     2 |    1 |     1 |    50% |
| application_sdk/common/error_codes.py                                             |    14 |    2 |    12 |    86% |
| application_sdk/common/utils.py                                                   |    16 |    2 |    14 |    88% |
| application_sdk/decorators/__init__.py                                            |     1 |    1 |     0 |     0% |
| application_sdk/decorators/locks.py                                               |     3 |    2 |     1 |    33% |
| application_sdk/decorators/mcp_tool.py                                            |     3 |    1 |     2 |    67% |
| application_sdk/docgen/__init__.py                                                |     5 |    2 |     3 |    60% |
| application_sdk/docgen/exporters/__init__.py                                      |     1 |    1 |     0 |     0% |
| application_sdk/docgen/exporters/mkdocs.py                                        |     7 |    3 |     4 |    57% |
| application_sdk/docgen/models/__init__.py                                         |     1 |    1 |     0 |     0% |
| application_sdk/docgen/models/export/__init__.py                                  |     1 |    1 |     0 |     0% |
| application_sdk/docgen/models/export/page.py                                      |     2 |    1 |     1 |    50% |
| application_sdk/docgen/models/manifest/__init__.py                                |     2 |    1 |     1 |    50% |
| application_sdk/docgen/models/manifest/customer.py                                |     3 |    1 |     2 |    67% |
| application_sdk/docgen/models/manifest/internal.py                                |     2 |    1 |     1 |    50% |
| application_sdk/docgen/models/manifest/metadata.py                                |     2 |    1 |     1 |    50% |
| application_sdk/docgen/models/manifest/page.py                                    |     2 |    1 |     1 |    50% |
| application_sdk/docgen/models/manifest/section.py                                 |     2 |    1 |     1 |    50% |
| application_sdk/docgen/parsers/__init__.py                                        |     1 |    1 |     0 |     0% |
| application_sdk/docgen/parsers/directory.py                                       |    13 |    2 |    11 |    85% |
| application_sdk/docgen/parsers/manifest.py                                        |     6 |    1 |     5 |    83% |
| application_sdk/events/__init__.py                                                |     1 |    0 |     1 |   100% |
| application_sdk/events/models.py                                                  |    12 |    1 |    11 |    92% |
| application_sdk/handlers/__init__.py                                              |     7 |    1 |     6 |    86% |
| application_sdk/handlers/base.py                                                  |     7 |    1 |     6 |    86% |
| application_sdk/handlers/sql.py                                                   |    19 |    6 |    13 |    68% |
| application_sdk/inputs/__init__.py                                                |     6 |    1 |     5 |    83% |
| application_sdk/inputs/iceberg.py                                                 |     7 |    3 |     4 |    57% |
| application_sdk/inputs/json.py                                                    |     8 |    2 |     6 |    75% |
| application_sdk/inputs/parquet.py                                                 |     8 |    1 |     7 |    88% |
| application_sdk/inputs/sql_query.py                                               |    11 |    1 |    10 |    91% |
| application_sdk/interceptors/__init__.py                                          |     1 |    1 |     0 |     0% |
| application_sdk/interceptors/cleanup.py                                           |     7 |    1 |     6 |    86% |
| application_sdk/interceptors/events.py                                            |     9 |    1 |     8 |    89% |
| application_sdk/interceptors/lock.py                                              |    10 |    2 |     8 |    80% |
| application_sdk/mcp/__init__.py                                                   |     1 |    0 |     1 |   100% |
| application_sdk/observability/__init__.py                                         |     1 |    1 |     0 |     0% |
| application_sdk/observability/logger_adaptor.py                                   |    31 |    3 |    28 |    90% |
| application_sdk/observability/metrics_adaptor.py                                  |    16 |    2 |    14 |    88% |
| application_sdk/observability/observability.py                                    |    24 |    1 |    23 |    96% |
| application_sdk/observability/traces_adaptor.py                                   |    16 |    1 |    15 |    94% |
| application_sdk/observability/utils.py                                            |     4 |    1 |     3 |    75% |
| application_sdk/observability/decorators/observability_decorator.py               |     7 |    4 |     3 |    43% |
| application_sdk/outputs/__init__.py                                               |    10 |    0 |    10 |   100% |
| application_sdk/outputs/iceberg.py                                                |     5 |    1 |     4 |    80% |
| application_sdk/outputs/json.py                                                   |     9 |    1 |     8 |    89% |
| application_sdk/outputs/parquet.py                                                |     9 |    1 |     8 |    89% |
| application_sdk/server/__init__.py                                                |     4 |    0 |     4 |   100% |
| application_sdk/server/fastapi/__init__.py                                        |    24 |    5 |    19 |    79% |
| application_sdk/server/fastapi/models.py                                          |    27 |   27 |     0 |     0% |
| application_sdk/server/fastapi/utils.py                                           |     2 |    0 |     2 |   100% |
| application_sdk/server/fastapi/middleware/logmiddleware.py                        |     4 |    4 |     0 |     0% |
| application_sdk/server/fastapi/middleware/metrics.py                              |     3 |    3 |     0 |     0% |
| application_sdk/server/fastapi/routers/__init__.py                                |     1 |    1 |     0 |     0% |
| application_sdk/server/fastapi/routers/server.py                                  |     8 |    2 |     6 |    75% |
| application_sdk/servers/mcp/server.py                                             |    14 |    0 |    14 |   100% |
| application_sdk/services/__init__.py                                              |     1 |    0 |     1 |   100% |
| application_sdk/services/atlan_storage.py                                         |     5 |    0 |     5 |   100% |
| application_sdk/services/eventstore.py                                            |     4 |    0 |     4 |   100% |
| application_sdk/services/objectstore.py                                           |    15 |    0 |    15 |   100% |
| application_sdk/services/secretstore.py                                           |    10 |    0 |    10 |   100% |
| application_sdk/services/statestore.py                                            |     8 |    1 |     7 |    88% |
| application_sdk/test_utils/__init__.py                                            |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/workflow_monitoring.py                                 |     3 |    0 |     3 |   100% |
| application_sdk/test_utils/e2e/__init__.py                                        |    14 |    2 |    12 |    86% |
| application_sdk/test_utils/e2e/base.py                                            |    16 |    2 |    14 |    88% |
| application_sdk/test_utils/e2e/client.py                                          |    10 |    2 |     8 |    80% |
| application_sdk/test_utils/e2e/conftest.py                                        |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/e2e/utils.py                                           |     3 |    1 |     2 |    67% |
| application_sdk/test_utils/hypothesis/__init__.py                                 |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/__init__.py                      |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/sql_client.py                    |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/temporal.py                      |     6 |    1 |     5 |    83% |
| application_sdk/test_utils/hypothesis/strategies/clients/__init__.py              |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/clients/sql.py                   |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/common/__init__.py               |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/common/logger.py                 |     3 |    0 |     3 |   100% |
| application_sdk/test_utils/hypothesis/strategies/handlers/__init__.py             |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/handlers/sql/__init__.py         |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/handlers/sql/sql_metadata.py     |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/handlers/sql/sql_preflight.py    |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/inputs/__init__.py               |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/inputs/json_input.py             |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/inputs/parquet_input.py          |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/outputs/__init__.py              |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/outputs/json_output.py           |     2 |    1 |     1 |    50% |
| application_sdk/test_utils/hypothesis/strategies/outputs/statestore.py            |     3 |    1 |     2 |    67% |
| application_sdk/test_utils/hypothesis/strategies/server/__init__.py               |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/hypothesis/strategies/server/fastapi/__init__.py       |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/scale_data_generator/__init__.py                       |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/scale_data_generator/config_loader.py                  |    10 |    4 |     6 |    60% |
| application_sdk/test_utils/scale_data_generator/data_generator.py                 |    10 |    3 |     7 |    70% |
| application_sdk/test_utils/scale_data_generator/driver.py                         |     3 |    3 |     0 |     0% |
| application_sdk/test_utils/scale_data_generator/output_handler/__init__.py        |     1 |    1 |     0 |     0% |
| application_sdk/test_utils/scale_data_generator/output_handler/base.py            |     7 |    3 |     4 |    57% |
| application_sdk/test_utils/scale_data_generator/output_handler/csv_handler.py     |     5 |    5 |     0 |     0% |
| application_sdk/test_utils/scale_data_generator/output_handler/json_handler.py    |     5 |    5 |     0 |     0% |
| application_sdk/test_utils/scale_data_generator/output_handler/parquet_handler.py |     6 |    6 |     0 |     0% |
| application_sdk/transformers/__init__.py                                          |     3 |    1 |     2 |    67% |
| application_sdk/transformers/atlas/__init__.py                                    |     6 |    1 |     5 |    83% |
| application_sdk/transformers/atlas/sql.py                                         |    25 |    4 |    21 |    84% |
| application_sdk/transformers/common/__init__.py                                   |     1 |    1 |     0 |     0% |
| application_sdk/transformers/common/utils.py                                      |     6 |    0 |     6 |   100% |
| application_sdk/transformers/query/__init__.py                                    |    11 |    2 |     9 |    82% |
| application_sdk/workflows/__init__.py                                             |     4 |    0 |     4 |   100% |
| application_sdk/workflows/metadata_extraction/__init__.py                         |     2 |    2 |     0 |     0% |
| application_sdk/workflows/metadata_extraction/sql.py                              |     8 |    0 |     8 |   100% |
| application_sdk/workflows/query_extraction/__init__.py                            |     2 |    2 |     0 |     0% |
| application_sdk/workflows/query_extraction/sql.py                                 |     4 |    0 |     4 |   100% |
| examples/application_custom_fastapi.py                                            |    14 |   14 |     0 |     0% |
| examples/application_fastapi.py                                                   |     9 |    9 |     0 |     0% |
| examples/application_hello_world.py                                               |     7 |    7 |     0 |     0% |
| examples/application_sql.py                                                       |     5 |    4 |     1 |    20% |
| examples/application_sql_miner.py                                                 |     5 |    4 |     1 |    20% |
| examples/application_sql_with_custom_pyatlan_transformer.py                       |    11 |    9 |     2 |    18% |
| examples/application_sql_with_custom_transformer.py                               |     9 |    8 |     1 |    11% |
| examples/run_examples.py                                                          |     2 |    1 |     1 |    50% |
| tests/__init__.py                                                                 |     1 |    1 |     0 |     0% |
| tests/conftest.py                                                                 |     3 |    0 |     3 |   100% |
| tests/unit/__init__.py                                                            |     1 |    1 |     0 |     0% |
| tests/unit/test_worker.py                                                         |    10 |    5 |     5 |    50% |
| tests/unit/activities/__init__.py                                                 |     1 |    1 |     0 |     0% |
| tests/unit/activities/test_activities.py                                          |    34 |    0 |    34 |   100% |
| tests/unit/activities/test_lock_management.py                                     |    11 |    0 |    11 |   100% |
| tests/unit/activities/common/__init__.py                                          |     1 |    1 |     0 |     0% |
| tests/unit/activities/common/test_utils.py                                        |    22 |   10 |    12 |    55% |
| tests/unit/activities/metadata_extraction/__init__.py                             |     1 |    1 |     0 |     0% |
| tests/unit/activities/metadata_extraction/test_sql.py                             |    56 |   36 |    20 |    36% |
| tests/unit/activities/query_extraction/__init__.py                                |     1 |    1 |     0 |     0% |
| tests/unit/application/__init__.py                                                |     1 |    1 |     0 |     0% |
| tests/unit/application/test_application.py                                        |    36 |    3 |    33 |    92% |
| tests/unit/application/test_mcp_integration.py                                    |    25 |    0 |    25 |   100% |
| tests/unit/application/metadata_extraction/test_sql.py                            |    30 |    6 |    24 |    80% |
| tests/unit/clients/__init__.py                                                    |     1 |    1 |     0 |     0% |
| tests/unit/clients/test_async_sql_client.py                                       |    15 |   14 |     1 |     7% |
| tests/unit/clients/test_atlan_auth.py                                             |    10 |    0 |    10 |   100% |
| tests/unit/clients/test_atlan_client.py                                           |     7 |    7 |     0 |     0% |
| tests/unit/clients/test_atlanauth.py                                              |    10 |    0 |    10 |   100% |
| tests/unit/clients/test_base_client.py                                            |    23 |    1 |    22 |    96% |
| tests/unit/clients/test_redis_client.py                                           |    40 |    0 |    40 |   100% |
| tests/unit/clients/test_sql_client.py                                             |    28 |    6 |    22 |    79% |
| tests/unit/clients/test_temporal_client.py                                        |    16 |    3 |    13 |    81% |
| tests/unit/common/test_aws_utils.py                                               |    30 |    1 |    29 |    97% |
| tests/unit/common/test_credential_utils.py                                        |    10 |    1 |     9 |    90% |
| tests/unit/common/test_utils.py                                                   |    74 |    6 |    68 |    92% |
| tests/unit/decorators/__init__.py                                                 |     1 |    0 |     1 |   100% |
| tests/unit/decorators/test_mcp_tool.py                                            |    19 |    2 |    17 |    89% |
| tests/unit/docgen/parsers/test_directory_parser.py                                |    14 |    3 |    11 |    79% |
| tests/unit/docgen/parsers/test_manifest_parser.py                                 |    12 |   12 |     0 |     0% |
| tests/unit/handlers/__init__.py                                                   |     1 |    1 |     0 |     0% |
| tests/unit/handlers/test_base_handler.py                                          |    26 |    2 |    24 |    92% |
| tests/unit/handlers/sql/test_auth.py                                              |    10 |    4 |     6 |    60% |
| tests/unit/handlers/sql/test_check_schemas_and_databases.py                       |    14 |    4 |    10 |    71% |
| tests/unit/handlers/sql/test_extract_allowed_schemas.py                           |    11 |    3 |     8 |    73% |
| tests/unit/handlers/sql/test_metadata.py                                          |    27 |   10 |    17 |    63% |
| tests/unit/handlers/sql/test_preflight_check.py                                   |    16 |   15 |     1 |     6% |
| tests/unit/handlers/sql/test_prepare_metadata.py                                  |    14 |    4 |    10 |    71% |
| tests/unit/handlers/sql/test_tables_check.py                                      |     9 |    6 |     3 |    33% |
| tests/unit/handlers/sql/test_validate_filters.py                                  |    12 |    4 |     8 |    67% |
| tests/unit/inputs/test_json.py                                                    |    21 |   12 |     9 |    43% |
| tests/unit/inputs/test_parquet.py                                                 |    37 |   12 |    25 |    68% |
| tests/unit/observability/__init__.py                                              |     1 |    1 |     0 |     0% |
| tests/unit/observability/test_logger_adaptor.py                                   |    20 |    2 |    18 |    90% |
| tests/unit/observability/test_metrics_adaptor.py                                  |    14 |    1 |    13 |    93% |
| tests/unit/observability/test_traces_adaptor.py                                   |    10 |    1 |     9 |    90% |
| tests/unit/outputs/test_iceberg.py                                                |    11 |    4 |     7 |    64% |
| tests/unit/outputs/test_json_output.py                                            |     7 |    6 |     1 |    14% |
| tests/unit/outputs/test_output.py                                                 |    19 |    6 |    13 |    68% |
| tests/unit/outputs/test_parquet_output.py                                         |    29 |    1 |    28 |    97% |
| tests/unit/server/__init__.py                                                     |     1 |    1 |     0 |     0% |
| tests/unit/server/fastapi/test_fastapi.py                                         |     8 |    3 |     5 |    62% |
| tests/unit/server/fastapi/routers/__init__.py                                     |     1 |    1 |     0 |     0% |
| tests/unit/server/fastapi/routers/server.py                                       |     1 |    1 |     0 |     0% |
| tests/unit/server/mcp/__init__.py                                                 |     1 |    0 |     1 |   100% |
| tests/unit/server/mcp/test_server.py                                              |    35 |    5 |    30 |    86% |
| tests/unit/services/test_atlan_storage.py                                         |    10 |    0 |    10 |   100% |
| tests/unit/services/test_eventstore.py                                            |    18 |    0 |    18 |   100% |
| tests/unit/services/test_objectstore.py                                           |    12 |    5 |     7 |    58% |
| tests/unit/services/test_statestore.py                                            |     6 |    6 |     0 |     0% |
| tests/unit/transformers/__init__.py                                               |     1 |    1 |     0 |     0% |
| tests/unit/transformers/atlas/__init__.py                                         |     1 |    1 |     0 |     0% |
| tests/unit/transformers/atlas/test_column.py                                      |    17 |    6 |    11 |    65% |
| tests/unit/transformers/atlas/test_database.py                                    |     8 |    6 |     2 |    25% |
| tests/unit/transformers/atlas/test_function.py                                    |     9 |    5 |     4 |    44% |
| tests/unit/transformers/atlas/test_procedure.py                                   |     7 |    6 |     1 |    14% |
| tests/unit/transformers/atlas/test_schema.py                                      |     8 |    6 |     2 |    25% |
| tests/unit/transformers/atlas/test_table.py                                       |    13 |    6 |     7 |    54% |
| tests/unit/transformers/query/test_sql_transformer.py                             |    14 |    4 |    10 |    71% |
| tests/unit/transformers/query/test_sql_transformer_output_validation.py           |     5 |    2 |     3 |    60% |
| tests/unit/workflows/metadata_extraction/test_sql_workflow.py                     |     9 |    4 |     5 |    56% |
| tests/unit/workflows/query_extraction/__init__.py                                 |     1 |    1 |     0 |     0% |
| tests/unit/workflows/query_extraction/test_sql.py                                 |     8 |    3 |     5 |    62% |
|-----------------------------------------------------------------------------------|-------|------|-------|--------|
| TOTAL                                                                             |  1976 |  562 |  1414 |  71.6% |
---------------- RESULT: PASSED (minimum: 30.0%, actual: 71.6%) ----------------

Copy link

github-actions bot commented Sep 8, 2025

📦 Trivy Vulnerability Scan Results

Schema Version Created At Artifact Type
2 2025-09-15T11:46:25.382528564Z . filesystem

Report Summary

Target Type Vulnerabilities . filesystem ✅ None found

Scan Result Details

✅ No vulnerabilities found during the scan for ..

Copy link

github-actions bot commented Sep 8, 2025

📦 Trivy Secret Scan Results

Schema Version Created At Artifact Type
2 2025-09-15T11:46:35.32644653Z . filesystem

Report Summary

Target Type Secrets . filesystem ✅ None found

Scan Result Details

✅ No secrets found during the scan for ..

@atlan-ci
Copy link
Collaborator

atlan-ci commented Sep 8, 2025

☂️ Python Coverage

current status: ✅

Overall Coverage

Lines Covered Coverage Threshold Status
6438 4486 70% 0% 🟢

New Files

No new covered files...

Modified Files

No covered modified files...

updated for commit: 6f5534c by action🐍

Copy link

github-actions bot commented Sep 8, 2025

🛠 Full Test Coverage Report: https://k.atlan.dev/coverage/application-sdk/pr/698

@junaidrahim
Copy link
Collaborator

junaidrahim commented Sep 9, 2025

@AdvitXAtlan Let's refactor it in the following direction

  1. Let's mount the MCP server to the underlying FastAPI server so that both can run from teh same port (guide here)
  2. Let's only support streamable HTTP for the transport as of now, apps are microservices and API would be the common instrument by which developers would debug and start their apps
  3. The ideal dev experience we want to aim for is the following -
    1. Developer tags the activities or functions they want to expose as MCP tools with the provided decorator, they add all the necessary metadata (descriptions etc)
    2. Developer just turns the enable_mcp flag as true in the BaseApplication object they create
    3. Just doing the above does all the tool discovery loop and mounts everything on the underlying FastAPI server on the /mcp route. This should be all to setup mcp, let's not expect developers to run two more commands like await app.start_mcp_server() to start it.
  4. Let's also explore if we can integrate the MCP Inspector somehow, maybe we can log something like "if you want to debug the mcp server you can use this"
  5. Let's move the decorator to application_sdk/decorators/mcp_tool.py and let's move the server to application_sdk/servers/mcp/server.py

Core Features:
- Added @mcp_tool decorator for marking activities as MCP tools
- Added MCPServer class that auto-discovers decorated activities
- Enhanced BaseApplication with enable_mcp parameter and MCP methods
- Added mcp optional dependency group

Architecture:
- Activities marked with @mcp_tool are automatically exposed
- MCPServer reuses existing activity discovery logic from workflows
- Clean integration: apps just add decorators + enable_mcp=True
- No manual MCP server code needed in individual apps
- Add @mcp_tool decorator for marking activities as MCP tools
- Implement MCPServer class with automatic tool discovery
- Mount FastMCP server on FastAPI at /mcp endpoint
- Support streamable HTTP transport for AI agent integration
- Enable MCP through BaseApplication enable_mcp flag
- Add FastMCP 2.0 as optional dependency
- Support Claude Desktop integration via npx mcp-remote
- Add Pydantic BaseModel automatic parameter expansion for AI-friendly tools
- Implement comprehensive unit test suite for MCP integration (37 tests)
- Fix @mcp_tool decorator to support both @mcp_tool and @mcp_tool() syntax
- Restructure test folders to mirror source code structure per standards
- Add FastMCP integration test when library is available
- Fix parameter ordering in Pydantic expansion (required before optional)
- Improve type comparisons and remove unused imports per linting
@AdvitXAtlan AdvitXAtlan force-pushed the feature/mcp-sdk-integration branch from 8fc9917 to 6f5534c Compare September 15, 2025 11:45
# ... activity implementation unchanged ...
"""

def decorator(f):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add a functools.wraps here

Comment on lines +35 to +41
@mcp_tool
async def simple_activity(self, param: str) -> str:
pass

@mcp_tool(description="Fetch random GIF from Giphy API")
async def fetch_gif(self, search_term: str) -> str:
# ... activity implementation unchanged ...
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add the >>> prefix to the lines in this section of the docstring indicating the python REPL.

You can find an example here

This should fix the failing docs action

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants