Skip to content

Commit 9757277

Browse files
committed
Address copilot feedback
1 parent 4e3bb94 commit 9757277

6 files changed

Lines changed: 35 additions & 36 deletions

File tree

.mcp.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
},
77
"image-search-azure": {
88
"type": "http",
9-
"url": "https://<your-mcp-container-app>/mcp"
9+
"url": "https://ca-mcp-dzwimtrf5gzou.orangeriver-094d6c5a.westus.azurecontainerapps.io/mcp"
1010
}
1111
}
1212
}

README.md

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -100,30 +100,44 @@ When `setup_search_service.py` runs (automatically during `azd up`, or manually)
100100
1. **Blob upload** – Images from the `pictures/` folder are uploaded to an Azure Blob Storage container. Only files placed directly under `pictures/` are uploaded.
101101
2. **Data source** – A Search data source is configured to point at that blob container.
102102
3. **Skillset** – Two skills are applied to each image:
103-
- [`VisionVectorizeSkill`](https://learn.microsoft.com/azure/search/cognitive-search-skill-vision-vectorize) generates a 1024-dimensional multimodal embedding using Azure AI Vision.
104-
- [`ChatCompletionSkill`](https://learn.microsoft.com/azure/search/chat-completion-skill-example-usage) (optional) produces a natural-language description of each image, stored as `verbalized_image`.
103+
* [`VisionVectorizeSkill`](https://learn.microsoft.com/azure/search/cognitive-search-skill-vision-vectorize) generates a 1024-dimensional multimodal embedding using Azure AI Vision.
104+
* [`ChatCompletionSkill`](https://learn.microsoft.com/azure/search/chat-completion-skill-example-usage) (optional) produces a natural-language description of each image, stored as `verbalized_image`.
105105
4. **Index** – Results are written to a Search index with an `embedding` vector field backed by an HNSW algorithm, plus a built-in AI Vision vectorizer so that query text is embedded at search time without extra code.
106106
5. **Indexer** – Runs the pipeline: blob → normalized images → skills → index projections. Each image within a blob becomes its own indexed document.
107107

108108
At query time, the search service vectorizes the text query using the same AI Vision model and performs an approximate nearest-neighbor search over the stored embeddings.
109109

110-
## Running locally
110+
## Testing deployed endpoints
111111

112-
You can only run locally **after** having successfully run the `azd up` command. If you haven't yet, follow the steps in [Azure deployment](#azure-deployment) above.
112+
After running `azd up`, you can test both deployed Container Apps.
113113

114-
### Web app
114+
### Deployed web app
115115

116-
1. Run `azd auth login`
117-
2. Change dir to `app` and run `./start.ps1` or `./start.sh` depending on your OS.
118-
3. Open a browser and navigate to `http://localhost:50505`
116+
1. Run `azd env get-value SERVICE_ACA_URI` to get the deployed web app URL.
117+
2. Open the URL in a browser.
119118

120-
### MCP server
119+
### Deployed MCP server
121120

122-
1. Run `azd auth login`
123-
2. Run `python app/backend/mcp_server.py`
124-
3. The server starts on `http://localhost:8001`. Add it to your MCP client configuration (e.g. VS Code or Claude Desktop) pointing at that URL.
121+
1. Run `azd env get-value SERVICE_MCP_URI` to get the deployed MCP server URL.
122+
2. Append `/mcp` to the URL.
123+
3. In `.mcp.json`, replace the `url` for the `image-search-azure` entry under `mcpServers` with the resulting URL.
124+
4. Open your MCP client and use the `image-search-azure` server.
125+
126+
## Testing local endpoints
127+
128+
You can only run the endpoints locally **after** successfully running `azd up`. If you haven't yet, follow the steps in [Azure deployment](#azure-deployment) above.
129+
130+
### Local web app
131+
132+
1. Run `azd auth login`.
133+
2. Change to the `app` directory and run `./start.ps1` or `./start.sh`, depending on your OS.
134+
3. Open `http://localhost:50505` in a browser.
135+
136+
### Local MCP server
125137

126-
To connect to a deployed MCP server instead, update `.vscode/mcp.json` with your deployed Container App hostname and append `/mcp` (for example, using the `SERVICE_MCP_URI` output from `azd up`).
138+
1. Run `azd auth login`.
139+
2. Run `python app/backend/mcp_server.py`.
140+
3. Open your MCP client and use the `image-search-local` server from `.mcp.json`, which connects to `http://localhost:8001/mcp`.
127141

128142
## Adding new images
129143

app/backend/image-viewer.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,9 @@ <h2 id="title"></h2>
136136
frame.innerHTML = "";
137137
const el = document.createElement("img");
138138
el.src = `data:${img.mimeType || "image/jpeg"};base64,${img.data}`;
139-
el.alt = "Blob image";
139+
el.alt = img.filename || "Image";
140140
frame.appendChild(el);
141-
title.textContent = img.title || img.filename || "Image";
141+
title.textContent = img.filename || "Image";
142142
description.textContent = img.description || "";
143143
description.hidden = !img.description;
144144
metadata.textContent = [

app/backend/mcp_server.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,6 @@ def get_image_mime_type(filename: str) -> str:
171171
return "image/jpeg"
172172

173173

174-
def get_image_title(filename: str) -> str:
175-
"""Create a readable image title from a blob filename."""
176-
stem = Path(unquote(filename)).stem
177-
return " ".join(stem.replace("_", " ").replace("-", " ").split()).title()
178-
179-
180174
THUMBNAIL_SIZE = (256, 256)
181175

182176

@@ -214,11 +208,13 @@ async def display_image_files(
214208
"Optional image descriptions from image_search, in the same order as filenames.",
215209
] = None,
216210
) -> ToolResult:
217-
"""Fetch images by filename and render them in a carousel with readable titles, descriptions, and file details."""
211+
"""Fetch images by filename and render them in a carousel with descriptions and file details."""
218212
if len(filenames) < 1:
219213
raise ValueError("Provide at least one filename.")
220214
if descriptions is not None and len(descriptions) != len(filenames):
221-
raise ValueError("Descriptions must have the same number of items as filenames.")
215+
raise ValueError(
216+
"Descriptions must have the same number of items as filenames."
217+
)
222218

223219
blob_service_client = get_blob_service_client()
224220

@@ -250,7 +246,6 @@ async def display_image_files(
250246
image_results.append(
251247
{
252248
"filename": filename,
253-
"title": get_image_title(filename),
254249
"description": descriptions[image_index] if descriptions else "",
255250
"mimeType": mime_type,
256251
"width": width,

app/frontend/tsconfig.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@
55
"lib": ["DOM", "DOM.Iterable", "ESNext"],
66
"allowJs": false,
77
"skipLibCheck": true,
8-
"esModuleInterop": false,
98
"allowSyntheticDefaultImports": true,
109
"strict": true,
1110
"forceConsistentCasingInFileNames": true,
1211
"module": "ESNext",
13-
"moduleResolution": "Node",
12+
"moduleResolution": "Bundler",
1413
"resolveJsonModule": true,
1514
"isolatedModules": true,
1615
"noEmit": true,

tests/test_mcp_server.py

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)