Skip to content

Chapter 4 · Build

Repository Anatomy & Python Basics

A map of the project folders, plus the small set of Python ideas you need to read the code with confidence. You don't have to be a Python expert — just comfortable with these six concepts.

🎯 What you'll be able to do

  • Navigate the project folders and know what each is responsible for
  • Read async functions, context managers, and Pydantic models
  • Understand modules, packages, and environment variables
  • Know which folders you'll touch first as a beginner

Repository layout

Here is the whole project at a glance. The comments show what each file is for — you'll meet them in detail in the Implementation Walkthrough.

Project structure
jira-mcp-copilot-studio
|-- app
|   |-- server.py          # entry point, builds the FastMCP app
|   |-- middleware.py      # origin / gateway / bearer checks
|   |-- config.py          # settings from env vars and .env
|   |-- context.py         # request-scoped token storage
|   |-- errors.py          # error envelope helpers
|   |-- telemetry.py       # logging + redaction + App Insights
|   |-- auth/bearer.py     # token + Jira site resolution
|   |-- jira/client.py     # async Jira REST client
|   |-- jira/trim.py       # payload trimming models
|   |-- tools/__init__.py  # MCP tool registration
|-- docs                   # implementation, deployment, security docs
|-- infra                  # main.bicep, containerapp.bicep, apim-policy.xml
|-- openapi                # mcp-connector.swagger.json, rest-fallback
|-- scripts                # run_local.ps1, deploy.ps1, smoke.py
|-- tests                  # unit tests
|-- Dockerfile
|-- pyproject.toml
|-- requirements.txt
|-- azure.yaml

What each area owns

AreaResponsibility
appRuntime server code.
app/toolsMCP tool definitions.
app/jiraJira API client and payload trimming.
app/authDelegated bearer token and Jira site resolution.
infraAzure infrastructure (Bicep, APIM policy).
openapiCopilot Studio connector definitions.
scriptsLocal run, deployment, and smoke validation scripts.
testsUnit tests.
docsProduction docs and architecture decisions.
What should a beginner touch first?
Start by reading app/tools/__init__.py (the tool menu) and app/config.py (the settings). Leave app/middleware.py and the infra/ Bicep files alone until you've read their chapters — small changes there have big security and deployment consequences.

Python ideas you'll use

Module

A .py file is a module. app/server.py is imported as app.server.

Package

A folder with __init__.py is a package. The app folder is a package.

Environment variable

Configures the app without changing code, e.g. $env:MAX_RESPONSE_BYTES = "90000". Read via pydantic-settings in config.py.

Async functions

The server uses asynchronous I/O because web servers spend most of their time waiting for network calls. An async function can wait for one operation without blocking the whole server.

Python
async def jira_whoami() -> dict:
    ...

Context manager

The async with block guarantees setup and cleanup happen reliably — here, it opens an HTTP client, resolves the Jira site, and closes the client afterward.

Python
async with JiraClient() as jira:
    return await jira.whoami()

Pydantic model

Pydantic models define structured data. In app/jira/trim.py, IssueSummary defines the compact issue shape returned to the agent — predictable and small, instead of raw Jira JSON.

Python
class IssueSummary(BaseModel):
    id: str | None = None
    key: str | None = None
    status: str | None = None
    summary: str | None = None
    assignee: str | None = None
    url: str | None = None

Concept check

Why does a web server benefit from async functions even though most code in this project isn't doing heavy computation?

📌 Chapter summary

  • app/ holds runtime code; infra/, openapi/, scripts/, and tests/ hold deployment, connector, automation, and tests.
  • You only need six Python ideas: module, package, async functions, context managers, Pydantic models, and environment variables.

✅ End-of-chapter review

0/4 done