AI Automation & Agents  

Enabling APIs for AI first systems

API quick refresher

APIs are an integral part of our systems. All the modern systems of today are using APIs.

They follow the HTTP protocol using the following verbs, each of which brings its own advantage and necessity. To summarize each one of them, below is a quick refresher, using the analogy of a restaurant for each verb:

HTTP VerbNeed/PurposeRestaurant AnalogyIdempotent?
GETRetrieve data (read-only, safe)Looking at the restaurant menuYes
POSTCreate new dataPlacing a new orderNo
PUTReplace the resource entirelyReplacing your entire meal with anotherYes
PATCHUpdate partiallyAsking for a side dessertNo
DELETERemoving resourceReturning an empty plateYes
OPTIONSFind allowed actionsAsking what things are allowed in a restaurantYes

Now, all the above verbs are standardized by all the widely adopted programming languages.

Now, let's create a basic FastAPI using Python.

  
    python -m venv venv #create virtual environment
 venv/Scripts/activate #activate virtual environment
 pip install fastapi[standard]
  

Now, create mainapp.py

  
    from fastapi import FastAPI

app = FastAPI()

menu = ["Pizza", "Burger", "Pasta"]
current_order: str = None


@app.get("/menu")
def get_menu():
    return {"menu": menu}
    

@app.post("/order")
def place_order(item: str):
    global current_order
    current_order = item
    return {"message": f"Order placed for {item}"}


@app.put("/order")
def replace_order(new_item: str):
    global current_order
    current_order = new_item
    return {"message": f"Order replaced with {new_item}"}


@app.delete("/order")
def delete_order():
    global current_order
    current_order = None
    return {"message": "Order deleted (empty plate)"}


@app.patch("/order")
def patch_order(side_dish: str):
    global current_order
    if not current_order:
        return {"error": "No order to update"}
    current_order = f"{current_order} with {side_dish}"
    return {"message": f"Order updated: {current_order}"}


@app.options("/order")
def options_order():
    return {
        "allowed_methods": ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
        "message": "You can look at menu, place, replace, delete, or update an order."
    }
  

Start the app

  
    fastapi dev mainapp.py
  FastAPI   Starting development server 🚀

             Searching for package file structure from directories with __init__.py files
             Importing from E:\KnowledgeSharing\API Basics
 
    module   🐍 mainapp.py

      code   Importing the FastAPI app object from the module with the following code:

             from mainapp import app

       app   Using import string: mainapp:app

    server   Server started at http://127.0.0.1:8000
    server   Documentation at http://127.0.0.1:8000/docs

       tip   Running in development mode, for production use: fastapi run

             Logs:

      INFO   Will watch for changes in these directories: ['E:\\KnowledgeSharing\\API Basics']
      INFO   Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
      INFO   Started reloader process [12696] using WatchFiles
      INFO   Started server process [2952]
      INFO   Waiting for application startup.
      INFO   Application startup complete.
      INFO   127.0.0.1:54932 - "GET /docs HTTP/1.1" 200
      INFO   127.0.0.1:54932 - "GET /openapi.json HTTP/1.1" 200
  

Now our App is up and running,

fastapidemo

As you can see from the Swagger documentation above, all the endpoints are neatly organized.

It also contains /openapi.json if you look closely below the title - FastAPI

This Open API json is a specification (spec) file provided by all the popular frameworks in different programming languages.

What is the Open API spec?

Open API Specification (formerly was also known as the Swagger Specification), is language-agnostic standard for defining and documenting RESTful APIs. It provides a structured way to describe the endpoints, request/response formats, authentication methods, and other capabilities of an API. By using the Open API Spec, both humans and machines can easily understand how a service works without needing direct access to its source code, detailed documentation, or analyzing network traffic.

This makes it highly useful for developers, testers, and automated tools to generate client SDKs, server stubs, and interactive documentation, ultimately streamlining the entire API development and integration process.

Now, from our above API, we can see this spec file.

  
    {
  "openapi": "3.1.0",
  "info": {
    "title": "FastAPI",
    "version": "0.1.0"
  },
  "paths": {
    "/menu": {
      "get": {
        "summary": "Get Menu",
        "operationId": "get_menu_menu_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {

                }
              }
            }
          }
        }
      }
    },
    "/order": {
      "post": {
        "summary": "Place Order",
        "operationId": "place_order_order_post",
        "parameters": [
          {
            "name": "item",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Item"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {

                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Replace Order",
        "operationId": "replace_order_order_put",
        "parameters": [
          {
            "name": "new_item",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "title": "New Item"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {

                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete Order",
        "operationId": "delete_order_order_delete",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {

                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Patch Order",
        "operationId": "patch_order_order_patch",
        "parameters": [
          {
            "name": "side_dish",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Side Dish"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {

                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "options": {
        "summary": "Options Order",
        "operationId": "options_order_order_options",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {

                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
          }
        },
        "type": "object",
        "title": "HTTPValidationError"
      },
      "ValidationError": {
        "properties": {
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "type": "array",
            "title": "Location"
          },
          "msg": {
            "type": "string",
            "title": "Message"
          },
          "type": {
            "type": "string",
            "title": "Error Type"
          }
        },
        "type": "object",
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError"
      }
    }
  }
}
  

Now, let's convert it to be utilized by AI-first systems. For this, we will convert this to an MCP server. This MCP server is consumed by AI Agents such as GitHub Co-pilot, Claude desktop, etc, to perform actions.

In short, our APIs will be directly consumed by Agentic systems.

Let's install the FastMCP Python package.

  
    pip install fastmcp
  

Now let's create the mcpapp.py

  
    import httpx
from fastmcp import FastMCP

# Create an HTTP client for your API
client = httpx.AsyncClient(base_url="http://localhost:8000")

# Load your OpenAPI spec 
openapi_spec = httpx.get("http://localhost:8000/openapi.json").json()

# Create the MCP server
mcp = FastMCP.from_openapi(
    openapi_spec=openapi_spec,
    client=client,
    name="My Restaurant Assistant"
)

if __name__ == "__main__":
    mcp.run(transport="http", port=8001)
  

Start the app

  
    python mcpapp.py
[09/12/25 20:41:51] INFO     Using legacy OpenAPI parser. To use the new parser, set   server.py:2013
                             FASTMCP_EXPERIMENTAL_ENABLE_NEW_OPENAPI_PARSER=true. The                
                             new parser was introduced for testing in 2.11 and will                  
                             become the default soon.                                                
                    INFO     Created FastMCP OpenAPI server with 6 routes              openapi.py:827


╭────────────────────────────────────────────────────────────────────────────╮
│                                                                            │
│        _ __ ___  _____           __  __  _____________    ____    ____     │
│       _ __ ___ .'____/___ ______/ /_/  |/  / ____/ __ \  |___ \  / __ \    │
│      _ __ ___ / /_  / __ `/ ___/ __/ /|_/ / /   / /_/ /  ___/ / / / / /    │
│     _ __ ___ / __/ / /_/ (__  ) /_/ /  / / /___/ ____/  /  __/_/ /_/ /     │
│    _ __ ___ /_/    \____/____/\__/_/  /_/\____/_/      /_____(*)____/      │
│                                                                            │
│                                                                            │
│                                FastMCP  2.0                                │
│                                                                            │
│                                                                            │
│               🖥️  Server name:     My Restaurant Assistant                  │
│               📦 Transport:       Streamable-HTTP                          │
│               🔗 Server URL:      http://127.0.0.1:8001/mcp                │
│                                                                            │
│               🏎️  FastMCP version: 2.12.3                                   │
│               🤝 MCP SDK version: 1.14.0                                   │
│                                                                            │
│               📚 Docs:            https://gofastmcp.com                    │
│               🚀 Deploy:          https://fastmcp.cloud                    │
│                                                                            │
╰────────────────────────────────────────────────────────────────────────────╯


                    INFO     Starting MCP server 'My Restaurant Assistant' with        server.py:1572
                             transport 'http' on http://127.0.0.1:8001/mcp                           
E:\KnowledgeSharing\API Basics\venv\Lib\site-packages\websockets\legacy\__init__.py:6: DeprecationWarning: websockets.legacy is deprecated; see https://websockets.readthedocs.io/en/stable/howto/upgrade.html for upgrade instructions
  warnings.warn(  # deprecated in 14.0 - 2024-11-09
E:\KnowledgeSharing\API Basics\venv\Lib\site-packages\uvicorn\protocols\websockets\websockets_impl.py:17: DeprecationWarning: websockets.server.WebSocketServerProtocol is deprecated
  from websockets.server import WebSocketServerProtocol
INFO:     Started server process [7996]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8001 (Press CTRL+C to quit)
INFO:     127.0.0.1:53885 - "GET / HTTP/1.1" 404 Not Found
INFO:     127.0.0.1:53885 - "GET /favicon.ico HTTP/1.1" 404 Not Found
  

That's it !! Now, our app is up and running for consumption. Let's interact with it with the help of an Agent.

We can set up the VS Code agent by configuring the settings below in the workspace. File will be .vscode/mcp.json.

  
    {
	"servers": {
		"local-restaurant-mcp": {
			"url": "http://localhost:8001/mcp",
			"type": "http"
		}
	},
	"inputs": []
}
  

Now, let's interact with the agent. We will perform the two interactions:

  • Show menu - "Show me the menu"

  • Place order - "One pizza please"

Below is the screenshot of how seamlessly our AI Agent interacts with our APIs via the MCP server.

order_demo-img

That's it! Thanks for reading till the end. We learned how to build APIs, convert to an MCP server, and integrate with Agents.

API quick refresher

APIs are an integral part of our systems. All the modern systems of today are using APIs.

They follow the HTTP protocol using the following verbs, each of which brings its own advantage and necessity. To summarize each one of them, below is a quick refresher, using the analogy of a restaurant for each verb:

HTTP VerbNeed/PurposeRestaurant AnalogyIdempotent?
GETRetrieve data (read-only, safe)Looking at the restaurant menuYes
POSTCreate new dataPlacing a new orderNo
PUTReplace the resource entirelyReplacing your entire meal with anotherYes
PATCHUpdate partiallyAsking for a side dessertNo
DELETERemoving resourceReturning an empty plateYes
OPTIONSFind allowed actionsAsking what things are allowed in a restaurantYes

Now, all the above verbs are standardized by all the widely adopted programming languages.

Now, let's create a basic FastAPI using Python.

  
    python -m venv venv #create virtual environment
 venv/Scripts/activate #activate virtual environment
 pip install fastapi[standard]
  

Now, create mainapp.py

  
    from fastapi import FastAPI

app = FastAPI()

menu = ["Pizza", "Burger", "Pasta"]
current_order: str = None

@app.get("/menu")
def get_menu():
    return {"menu": menu}
    
@app.post("/order")
def place_order(item: str):
    global current_order
    current_order = item
    return {"message": f"Order placed for {item}"}

@app.put("/order")
def replace_order(new_item: str):
    global current_order
    current_order = new_item
    return {"message": f"Order replaced with {new_item}"}

@app.delete("/order")
def delete_order():
    global current_order
    current_order = None
    return {"message": "Order deleted (empty plate)"}

@app.patch("/order")
def patch_order(side_dish: str):
    global current_order
    if not current_order:
        return {"error": "No order to update"}
    current_order = f"{current_order} with {side_dish}"
    return {"message": f"Order updated: {current_order}"}

@app.options("/order")
def options_order():
    return {
        "allowed_methods": ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
        "message": "You can look at menu, place, replace, delete, or update an order."
    }
  

Start the app

  
    fastapi dev mainapp.py
  FastAPI   Starting development server 🚀

             Searching for package file structure from directories with __init__.py files
             Importing from E:\KnowledgeSharing\API Basics
 
    module   🐍 mainapp.py

      code   Importing the FastAPI app object from the module with the following code:

             from mainapp import app

       app   Using import string: mainapp:app

    server   Server started at http://127.0.0.1:8000
    server   Documentation at http://127.0.0.1:8000/docs

       tip   Running in development mode, for production use: fastapi run

             Logs:

      INFO   Will watch for changes in these directories: ['E:\\KnowledgeSharing\\API Basics']
      INFO   Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
      INFO   Started reloader process [12696] using WatchFiles
      INFO   Started server process [2952]
      INFO   Waiting for application startup.
      INFO   Application startup complete.
      INFO   127.0.0.1:54932 - "GET /docs HTTP/1.1" 200
      INFO   127.0.0.1:54932 - "GET /openapi.json HTTP/1.1" 200
  

Now our App is up and running,

fastapidemo

As you can see from the Swagger documentation above, all the endpoints are neatly organized.

It also contains /openapi.json if you look closely below the title - FastAPI

This Open API json is a specification (spec) file provided by all the popular frameworks in different programming languages.

What is the Open API spec?

Open API Specification (formerly was also known as the Swagger Specification), is language-agnostic standard for defining and documenting RESTful APIs. It provides a structured way to describe the endpoints, request/response formats, authentication methods, and other capabilities of an API. By using the Open API Spec, both humans and machines can easily understand how a service works without needing direct access to its source code, detailed documentation, or analyzing network traffic.

This makes it highly useful for developers, testers, and automated tools to generate client SDKs, server stubs, and interactive documentation, ultimately streamlining the entire API development and integration process.

Now, from our above API, we can see this spec file.

  
    {
  "openapi": "3.1.0",
  "info": {
    "title": "FastAPI",
    "version": "0.1.0"
  },
  "paths": {
    "/menu": {
      "get": {
        "summary": "Get Menu",
        "operationId": "get_menu_menu_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {

                }
              }
            }
          }
        }
      }
    },
    "/order": {
      "post": {
        "summary": "Place Order",
        "operationId": "place_order_order_post",
        "parameters": [
          {
            "name": "item",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Item"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {

                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Replace Order",
        "operationId": "replace_order_order_put",
        "parameters": [
          {
            "name": "new_item",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "title": "New Item"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {

                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete Order",
        "operationId": "delete_order_order_delete",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {

                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Patch Order",
        "operationId": "patch_order_order_patch",
        "parameters": [
          {
            "name": "side_dish",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Side Dish"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {

                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          }
        }
      },
      "options": {
        "summary": "Options Order",
        "operationId": "options_order_order_options",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {

                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "HTTPValidationError": {
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ValidationError"
            },
            "type": "array",
            "title": "Detail"
          }
        },
        "type": "object",
        "title": "HTTPValidationError"
      },
      "ValidationError": {
        "properties": {
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "integer"
                }
              ]
            },
            "type": "array",
            "title": "Location"
          },
          "msg": {
            "type": "string",
            "title": "Message"
          },
          "type": {
            "type": "string",
            "title": "Error Type"
          }
        },
        "type": "object",
        "required": [
          "loc",
          "msg",
          "type"
        ],
        "title": "ValidationError"
      }
    }
  }
}
  

Now, let's convert it to be utilized by AI-first systems. For this, we will convert this to an MCP server. This MCP server is consumed by AI Agents such as GitHub Co-pilot, Claude desktop, etc, to perform actions.

In short, our APIs will be directly consumed by Agentic systems.

Let's install the FastMCP Python package.

  
    pip install fastmcp
  

Now let's create the mcpapp.py

  
    import httpx
from fastmcp import FastMCP

# Create an HTTP client for your API
client = httpx.AsyncClient(base_url="http://localhost:8000")

# Load your OpenAPI spec 
openapi_spec = httpx.get("http://localhost:8000/openapi.json").json()

# Create the MCP server
mcp = FastMCP.from_openapi(
    openapi_spec=openapi_spec,
    client=client,
    name="My Restaurant Assistant"
)

if __name__ == "__main__":
    mcp.run(transport="http", port=8001)
  

Start the app

  
    python mcpapp.py
[09/12/25 20:41:51] INFO     Using legacy OpenAPI parser. To use the new parser, set   server.py:2013
                             FASTMCP_EXPERIMENTAL_ENABLE_NEW_OPENAPI_PARSER=true. The                
                             new parser was introduced for testing in 2.11 and will                  
                             become the default soon.                                                
                    INFO     Created FastMCP OpenAPI server with 6 routes              openapi.py:827


╭────────────────────────────────────────────────────────────────────────────╮
│                                                                            │
│        _ __ ___  _____           __  __  _____________    ____    ____     │
│       _ __ ___ .'____/___ ______/ /_/  |/  / ____/ __ \  |___ \  / __ \    │
│      _ __ ___ / /_  / __ `/ ___/ __/ /|_/ / /   / /_/ /  ___/ / / / / /    │
│     _ __ ___ / __/ / /_/ (__  ) /_/ /  / / /___/ ____/  /  __/_/ /_/ /     │
│    _ __ ___ /_/    \____/____/\__/_/  /_/\____/_/      /_____(*)____/      │
│                                                                            │
│                                                                            │
│                                FastMCP  2.0                                │
│                                                                            │
│                                                                            │
│               🖥️  Server name:     My Restaurant Assistant                  │
│               📦 Transport:       Streamable-HTTP                          │
│               🔗 Server URL:      http://127.0.0.1:8001/mcp                │
│                                                                            │
│               🏎️  FastMCP version: 2.12.3                                   │
│               🤝 MCP SDK version: 1.14.0                                   │
│                                                                            │
│               📚 Docs:            https://gofastmcp.com                    │
│               🚀 Deploy:          https://fastmcp.cloud                    │
│                                                                            │
╰────────────────────────────────────────────────────────────────────────────╯
                    INFO     Starting MCP server 'My Restaurant Assistant' with        server.py:1572
                             transport 'http' on http://127.0.0.1:8001/mcp                           
E:\KnowledgeSharing\API Basics\venv\Lib\site-packages\websockets\legacy\__init__.py:6: DeprecationWarning: websockets.legacy is deprecated; see https://websockets.readthedocs.io/en/stable/howto/upgrade.html for upgrade instructions
  warnings.warn(  # deprecated in 14.0 - 2024-11-09
E:\KnowledgeSharing\API Basics\venv\Lib\site-packages\uvicorn\protocols\websockets\websockets_impl.py:17: DeprecationWarning: websockets.server.WebSocketServerProtocol is deprecated
  from websockets.server import WebSocketServerProtocol
INFO:     Started server process [7996]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8001 (Press CTRL+C to quit)
INFO:     127.0.0.1:53885 - "GET / HTTP/1.1" 404 Not Found
INFO:     127.0.0.1:53885 - "GET /favicon.ico HTTP/1.1" 404 Not Found
  

That's it !! Now, our app is up and running for consumption. Let's interact with it with the help of an Agent.

We can set up the VS Code agent by configuring the settings below in the workspace. File will be .vscode/mcp.json.

  
    {
	"servers": {
		"local-restaurant-mcp": {
			"url": "http://localhost:8001/mcp",
			"type": "http"
		}
	},
	"inputs": []
}
  

Now, let's interact with the agent. We will perform the two interactions:

  • Show menu - "Show me the menu"

  • Place order - "One pizza please"

Below is the screenshot of how seamlessly our AI Agent interacts with our APIs via the MCP server.

order_demo-img

That's it! Thanks for reading till the end. We learned how to build APIs, convert to an MCP server, and integrate with Agents.