<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by ENTANGO on Medium]]></title>
        <description><![CDATA[Stories by ENTANGO on Medium]]></description>
        <link>https://medium.com/@entango?source=rss-486a4f96e33f------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*0Q8vUXycAtpE-pJwkyedvg.png</url>
            <title>Stories by ENTANGO on Medium</title>
            <link>https://medium.com/@entango?source=rss-486a4f96e33f------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 07:03:51 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@entango/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Connect your AI agents to Datalake to read and store data]]></title>
            <link>https://blog.devgenius.io/connect-your-ai-agents-to-datalake-to-read-and-store-data-c29ca720a31c?source=rss-486a4f96e33f------2</link>
            <guid isPermaLink="false">https://medium.com/p/c29ca720a31c</guid>
            <category><![CDATA[dotnet]]></category>
            <category><![CDATA[mcp-server]]></category>
            <category><![CDATA[ai-agent]]></category>
            <category><![CDATA[data-engineering]]></category>
            <dc:creator><![CDATA[ENTANGO]]></dc:creator>
            <pubDate>Thu, 15 Oct 2026 22:26:31 GMT</pubDate>
            <atom:updated>2026-10-16T08:48:14.684Z</atom:updated>
            <content:encoded><![CDATA[<p><em>How Datalake-MCP turns an Azure Data Lake Storage Gen2 account into a set of tools that Claude can navigate, query and write to</em></p><p>Most of the data a company cares about does not live in a database an LLM can talk to. It lives in a data lake: thousands of CSV and Parquet files, organised in folders by domain, year or source system. Getting an AI agent to use that data usually means writing a custom pipeline, exporting samples by hand, or pasting rows into a chat window.</p><p>The Model Context Protocol (MCP) gives us a cleaner option. If the data lake is exposed as an MCP server, any MCP-capable client (Claude Desktop, Claude Code, your own agent) can discover and use it as a set of typed tools.</p><p>That is what <strong>Datalake-MCP</strong> does. It is a .NET 9 MCP server that connects to an Azure Data Lake Storage Gen2 account and lets an agent:</p><p>- N<strong>avigate</strong> filesystems and directories,</p><p>- R<strong>ead</strong> CSV, Parquet, XML, text and markdown files, with filters, column projection and pagination,</p><p>- S<strong>ave</strong> text, markdown, CSV, Parquet and PDF files, with a searchable index of everything that has been written.</p><p>This post covers how it works internally and what it makes possible.</p><h3><strong>Architecture at a glance</strong></h3><p>User &lt;-&gt; Claude (Desktop / Code) ← MCP over stdio → Datalake.Mcp.Server (.NET 9)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bAQbY_N0V0gu4m3m1D_7qQ.png" /><figcaption>mcp architecture</figcaption></figure><p>The server runs as a .NET Generic Host and talks to the client over <strong>stdio</strong>. The client launches it as a child process, so there is no HTTP endpoint to secure and nothing to deploy. Connection settings (`AccountName`, `AccountKey`, `DefaultFileSystem`) come from .NET user-secrets in development, or from environment variables when the server is registered in the client.</p><p>The code is split into three layers:</p><p>- <strong>Tools</strong> (`DataLakeTools`): the MCP surface. Each method is a tool with a description and typed parameters that the model sees.</p><p>- <strong>Services</strong>: format-specific readers, the writer, the index and the row filter. They contain no Azure-specific code.</p><p>- <strong>DataLakeService</strong>: a thin wrapper over `Azure.Storage.Files.DataLake`, the only class that talks to the storage account.</p><h3><strong>The tool surface</strong></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GUlb5PVCaaykpmccMOlk1w.png" /><figcaption>mcp tools</figcaption></figure><p>The tools are designed to be called in sequence. A typical exploration goes `list_filesystems`, then `list_directory`, then `get_parquet_schema`, then `read_parquet`. The agent sees column names and types before it asks for rows, so it can write sensible filters instead of guessing.</p><h3><strong>Reading without loading: streaming by design</strong></h3><p>A data lake file can be gigabytes in size, and an LLM can only consume a tiny fraction of it. The server is built around that mismatch.</p><p><strong>Lazy remote reads.</strong> Files are opened with `DataLakeFileClient.OpenReadAsync`, which returns a stream that downloads only the bytes actually requested. Nothing is fetched up front.</p><h3><strong>Format-aware streaming</strong></h3><p>- CSV, text and markdown are read line by line and the read stops at the requested limit.</p><p>- XML is read element by element (tabular XML: a root with repeated record elements). DTD processing and external entity resolution are disabled, which prevents XXE attacks.</p><p>- Parquet is read one <strong>row group</strong> at a time, with <strong>column projection</strong>: if you ask for three columns, the others are never decoded. This is where Parquet’s columnar layout pays off.</p><p><strong>Pagination that does not re-read.</strong> Every read tool returns `truncated` and `nextOffset`. When a result is cut off, either by `maxRows` or by the tool-call size limit (about 1 MB), the agent calls the tool again with `offset = nextOffset` and gets the next page. The model walks a large file in chunks without any hidden state in the server.</p><h3><strong>Querying: server-side filters</strong></h3><p>The most useful feature for analytical work is the `filter` parameter on `read_csv`, `read_parquet` and `read_xml`. It is a list of conditions combined with AND:</p><p>```json</p><p>[</p><p>{“column”: “stato”, “operator”: “eq”, “value”: “APERTO”},</p><p>{“column”: “importo”, “operator”: “gt”, “value”: “1000”}</p><p>]</p><p>```</p><p>Supported operators are `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `contains`, `startswith`, `endswith`, `isnull` and `isnotnull`. Comparison semantics:</p><p>- numeric when both the cell and the value parse as numbers (invariant format, `12.5`),</p><p>- timestamp-aware for Parquet date columns when the value is a date,</p><p>- case-insensitive text otherwise.</p><p>Two design decisions matter here:</p><p>1. <strong>The filter runs inside the streaming loop, before `offset` and `maxRows`.</strong> The pagination counters therefore count only matching rows. “Give me the next 100 open orders over 1000” works as expected, and non-matching rows never reach the model’s context window.</p><p>2. <strong>Filters can reference columns that are not projected.</strong> You can filter on `stato` and return only `id` and `importo`.</p><p>A wrong column name or operator returns an error that lists the allowed values, so the agent can correct itself in the next call without human help.</p><p>A request like <em>*”show me the open orders above 1000&quot;*</em> becomes: look at the schema, build a filter, read with a projection, and summarise the result. The model never sees the other 99% of the file.</p><h3><strong>Writing back: safe by default</strong></h3><p>Reading is only half of the story. Agents are far more useful when they can leave something behind: a report, a cleaned dataset, a summary of an analysis. Write access to shared storage is also where things go wrong, so the write path was designed conservatively.</p><p>The `save_*` tools take a `path` (folders and subfolders are created if missing), a `fileSystem`, a `description` and an `overwrite` flag.</p><p><strong>No silent overwrite.</strong> Uploads are conditional (`If-None-Match: *`). If the file already exists and `overwrite` is not `true`, the call fails and the existing file is untouched. An agent cannot destroy data by accident, only by being explicitly told to.</p><p><strong>Validation before upload.</strong></p><p>- The path extension must match the format.</p><p>- CSV must have the same number of fields on every row.</p><p>- Parquet is built from a list of rows (column to value objects), with types inferred (bool, integer, decimal, string).</p><p>- PDF is received as base64, and the `%PDF-` header is checked.</p><h3><strong>The index: files you can find again</strong></h3><p>Each successful save is recorded in an <strong>index file</strong>, a CSV at the filesystem root (configured with `DataLake:SavedFilesIndexPath`, default `saved-files-index.csv`) with the columns:</p><p>```</p><p>path, name, format, sizeBytes, savedAt, description</p><p>```</p><p>Saving the same path again updates its row. Because several agents or sessions may write at the same time, the index is updated with <strong>optimistic concurrency</strong>: read the index and its ETag, apply the change, write back with `If-Match: &lt;ETag&gt;`. On a conflict the cycle restarts, up to 5 attempts. No locks, no lease management, and no lost updates.</p><p>The index is a plain CSV, so it can be read with `read_csv`, opened in Excel or loaded by any other tool.</p><p>On top of the index sits `search_file(nomeFile, tipoFile)`. It matches the file name with <em>*contains*</em> logic (case-insensitive) and can filter by type (csv, parquet, pdf, md, txt). When <strong>exactly one file matches</strong>, the tool also returns its content: the first `maxRows` rows for tabular files, text for txt and md, metadata only for PDF. The agent can ask for “last quarter’s margin report” and get the document in a single call.</p><h3><strong>What this enables</strong></h3><p>Once the connection is in place, several patterns become possible.</p><p><strong>1. Natural-language analytics over raw files.</strong> Ask questions about costs, orders or KPIs without building a dashboard first. The agent inspects the schema, filters, aggregates what comes back and explains it. It works well for ad-hoc questions that do not justify a BI project.</p><p><strong>2. Data exploration and profiling.</strong> Point the agent at an unfamiliar folder. It can list the files, read the schemas, sample rows, spot null-heavy columns and describe what the dataset seems to contain, which is a good first step when you inherit a lake nobody documented.</p><p><strong>3. Persistent agent output.</strong> Reports, generated markdown documentation, cleaned CSVs and Parquet extracts can be saved next to the data, indexed and found again later. The lake becomes the shared memory of your agents, backed by your existing storage, access control and retention rules.</p><p><strong>4. Multi-agent workflows with a shared medium.</strong> One agent extracts and filters data and saves a Parquet file. Another finds it with `search_file` and builds a summary. A third saves the PDF. The agents never talk directly. They coordinate through files and the index, and every step leaves an auditable artifact.</p><p><strong>5. Reference data lookups.</strong> Price lists, catalogues and code tables stored as CSV with a markdown index file can be searched by keyword and compared across years or regions, with the agent doing the matching that used to be done by hand.</p><p><strong>6. Domain skills on top of the tools.</strong> The repository includes a `SKILL.md` that teaches Claude how a specific lake is organised: folder conventions, table meanings, business terms (EVM, WBS, SAL and so on). The MCP provides the capabilities and the skill provides the domain knowledge. Together they let a general-purpose model act like a specialist for your data.</p><h3><strong>Getting started</strong></h3><p>1. Build the server: `dotnet build src/Datalake.Mcp.Server -c Release`</p><p>2. Add it to `%APPDATA%\Claude\claude_desktop_config.json` under `mcpServers`, with the DLL path in `args` and `DataLake__AccountName`, `DataLake__AccountKey` and `DataLake__DefaultFileSystem` in `env`.</p><p>3. Restart Claude Desktop. The `datalake` server and its tools appear in the tool list.</p><p>Then ask something like: <em>*”List the filesystems, find the Parquet files under `sales/2026`, and show me the open orders above 1000 with only id, customer and amount.”*</em></p><h3><strong>Security notes</strong></h3><p>- Never commit credentials. Use user-secrets or environment variables; `appsettings.json` ships with empty placeholders.</p><p>- The server authenticates with the <strong>account key</strong>, which grants full access to the account. For production, consider a dedicated storage account or a narrower credential, and be deliberate about which lake you connect to an agent.</p><p>- Writes are additive by default. `overwrite=true` is the only way to replace a file.</p><p>- Reads are bounded (`maxRows`, `maxLines`, the response size cap), so a careless prompt cannot stream a whole file into the model’s context.</p><h3><strong>Conclusion</strong></h3><p>An agent is only as useful as the data it can reach. Exposing Azure Data Lake Gen2 over MCP removes the glue code between the two: the agent can browse, filter, read and write through a small set of typed tools, while streaming reads, conditional writes and ETag-based indexing keep the server efficient and safe.</p><p>see open source project on Github</p><p><a href="https://github.com/alex1976/Datalake-MCP">https://github.com/alex1976/Datalake-MCP</a></p><p>Datalake-MCP is listed on <strong>mcpservers.org</strong></p><p><a href="https://mcpservers.org/servers/alex1976/datalake-mcp">https://mcpservers.org/servers/alex1976/datalake-mcp</a></p><p>If you have a datalake on Azure and an agent, try connecting them.</p><p><em>Tags: #MCP, #Azure Data Lake, #AI Agents, #Claude, #DotNET, #Data Engineering</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c29ca720a31c" width="1" height="1" alt=""><hr><p><a href="https://blog.devgenius.io/connect-your-ai-agents-to-datalake-to-read-and-store-data-c29ca720a31c">Connect your AI agents to Datalake to read and store data</a> was originally published in <a href="https://blog.devgenius.io/">Dev Genius</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Memory-MCP: Extracting Text from PDFs Without Breaking Reading Order with PdfPig]]></title>
            <link>https://medium.com/@entango/memory-mcp-extracting-text-from-pdfs-without-breaking-reading-order-with-pdfpig-82f05dde2e5b?source=rss-486a4f96e33f------2</link>
            <guid isPermaLink="false">https://medium.com/p/82f05dde2e5b</guid>
            <category><![CDATA[dotnet]]></category>
            <category><![CDATA[mcp-server]]></category>
            <category><![CDATA[agentic-ai]]></category>
            <dc:creator><![CDATA[ENTANGO]]></dc:creator>
            <pubDate>Thu, 24 Sep 2026 12:24:22 GMT</pubDate>
            <atom:updated>2026-09-24T12:24:22.862Z</atom:updated>
            <content:encoded><![CDATA[<p>The easy part of handling a PDF in an AI memory pipeline is opening the file. The hard part is getting text an LLM can actually reason about — not a garbled mess of interleaved columns, repeated page headers, and tables flattened into a single unreadable line.</p><p>In Memory-MCP, a persistent-memory MCP server for AI agents, this responsibility lives in a single class, PdfTextExtractor, built on <a href="https://github.com/UglyToad/PdfPig">PdfPig</a> (v0.1.15). It&#39;s worth walking through the implementation because the failure mode in this domain is silent: the document &quot;looks&quot; extracted fine, but the text is in the wrong order.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*I6v6zC8I9XNxdGhb" /></figure><h3>Why PdfPig, and why that matters architecturally</h3><p>PdfPig is a <strong>fully managed .NET library</strong> — no native dependencies, no wrapper around Ghostscript or a C library. That’s not a cosmetic detail. Elsewhere in the same system, IEmbeddingProvider and IFactExtractor require an external API key and may simply not be configured. IPdfTextExtractor has no such dependency, so it&#39;s <strong>always available</strong> — a user can upload and store a PDF&#39;s text even in a deployment with no LLM configured at all.</p><h3>The problem Page.Text doesn&#39;t solve</h3><p>PdfPig’s most obvious API is Page.Text, which concatenates glyphs in content-stream order — the order operators appear in the PDF&#39;s internal drawing instructions. For a single-column document, that&#39;s fine. For anything more realistic — two columns, a table, a header repeated on every page — content-stream order does not match human reading order. You get output like:</p><pre>Alpha one Beta one Alpha two Beta two Alpha three Beta three...</pre><p>when the actual intent was two columns read top-to-bottom in sequence: “Alpha one, Alpha two, Alpha three… then Beta one, Beta two…”.</p><p>This isn’t cosmetic. The extracted text is exactly what gets embedded and handed to the downstream fact extractor: wrong reading order means wrong or unrecoverable extracted facts. In the codebase this is treated explicitly as a <em>correctness concern</em>, not a nice-to-have.</p><h3>The three-stage layout analysis pipeline</h3><p>PdfTextExtractor.ExtractPageText doesn&#39;t reach for Page.Text first. It runs PdfPig&#39;s document layout analysis pipeline in three sequential stages:</p><pre>var words = NearestNeighbourWordExtractor.Instance.GetWords(page.Letters);<br>var blocks = DocstrumBoundingBoxes.Instance.GetBlocks(words);<br>var ordered = UnsupervisedReadingOrderDetector.Instance.Get(blocks);<br>var pageText = string.Join(&quot;\n\n&quot;, ordered.Select(block =&gt; block.Text));</pre><ol><li><strong>NearestNeighbourWordExtractor</strong> — PdfPig exposes individual glyphs (Letter) with their positions. This stage groups them into words using spatial proximity as the heuristic.</li><li><strong>DocstrumBoundingBoxes</strong> — implements the Docstrum (Document Structure Analysis) algorithm, which groups words into blocks/paragraphs based on bounding-box geometry: line alignment, typical spacing between words versus between columns.</li><li><strong>UnsupervisedReadingOrderDetector</strong> — reorders the resulting blocks according to an estimated human reading order, not content-stream order. This is the stage that actually fixes the two-column case.</li></ol><p>The ordered blocks are joined with &quot;\n\n&quot; — a blank line. That&#39;s the only &quot;structure&quot; the system preserves: each block is a paragraph, and the boundary between blocks survives into the stored text as an empty line. This is not Markdown in any literal sense — no #, no reconstructed lists, no tables — but it&#39;s the minimum useful granularity: it gives the downstream fact extractor a coherent unit to reason over instead of an undifferentiated wall of text.</p><h3>The parsing options, and why each one exists</h3><pre>private static readonly ParsingOptions Options = new()<br>{<br>    UseLenientParsing = true,<br>    SkipMissingFonts = true,<br>    UseActualText = true,<br>};</pre><ul><li><strong>UseLenientParsing</strong> and <strong>SkipMissingFonts</strong>: real-world PDFs are frequently slightly malformed (incomplete font embedding, dangling object references). Without these, PdfPig would throw on documents that any ordinary viewer opens without complaint.</li><li><strong>UseActualText</strong>: honors the PDF&#39;s /ActualText attribute, a spec-level mechanism that lets an author specify the &quot;real&quot; text behind a glyph sequence that would otherwise be unreadable — typographic ligatures, or text drawn out of logical order, which is common in tables produced by layout tools.</li></ul><h3>A two-level fallback, without swallowing errors entirely</h3><pre>try<br>{<br>    // NearestNeighbourWordExtractor -&gt; DocstrumBoundingBoxes -&gt; UnsupervisedReadingOrderDetector<br>    return string.IsNullOrWhiteSpace(pageText) ? page.Text : pageText;<br>}<br>catch (Exception ex) when (ex is not OperationCanceledException)<br>{<br>    return page.Text;<br>}</pre><p>A page with degenerate geometry (corrupted fonts, malformed coordinates) can make the segmentation algorithm throw, or produce zero blocks. In that case, falling back to page.Text for <strong>that one page</strong> beats both worse alternatives: failing the entire upload, or silently storing an empty document.</p><p>At the document level, any other exception (corrupted bytes, an unopenable PDF) is wrapped into a DocumentExtractionException carrying the original message — handled as an ordinary MCP tool error, not an unhandled exception that crashes the process.</p><h3>What this pipeline deliberately does not do</h3><p>Being explicit about the boundaries matters as much as explaining what works:</p><ul><li><strong>No OCR.</strong> A scanned (image-only) PDF with no text layer extracts as empty text, with no error. The UI surfaces this as “no extractable text found — memory extraction skipped.” OCR is explicitly out of scope at this stage.</li><li><strong>No embedded image extraction.</strong></li><li><strong>No structural table reconstruction.</strong> Tables benefit only indirectly: UseActualText recovers correct text from cells drawn out of logical order, and the reading-order detector mitigates — but doesn&#39;t fully solve — column/cell interleaving.</li><li><strong>No heading detection</strong> based on font size or boldness — there’s no generated #/## markup.</li></ul><h3>Where this text goes: two decoupled steps, not one automatic pipeline</h3><p>One architectural detail that’s often assumed implicitly but is explicit here: <strong>uploading a PDF and generating memories are two separate MCP tools</strong>, called in sequence by the client — not a single operation.</p><ol><li><strong>create_document</strong> receives the PDF as base64 bytes, calls PdfTextExtractor.ExtractTextAsync, and stores the result as the Document&#39;s RawContent. That&#39;s it — no fact extraction, no embedding, just source-of-truth storage.</li><li><strong>add_memory</strong>, called separately, takes that text (the full content, not chunked into fixed windows), computes an embedding, searches for similar candidate memories already in the space, and hands everything to an LLM-backed IFactExtractor, which pulls out atomic facts and links them semantically to existing memories in a graph. If no LLM is configured, the entire text becomes a single memory — a &quot;pre-graph&quot; fallback behavior.</li></ol><p>There’s no fixed-token chunker anywhere in the PdfPig path: the real chunking is semantic, and it happens inside the fact extractor’s LLM, not in the PDF parsing layer. PdfPig’s job ends earlier — handing the LLM text in the right order.</p><h3>The general lesson</h3><p>This kind of pipeline illustrates something often underweighted in RAG systems: <strong>upstream extraction quality is a silent multiplier on everything downstream</strong>. An embedding computed over text with interleaved columns produces vectors that don’t represent the actual document — and no retriever, however sophisticated, can fix that after the fact. Investing in layout analysis before embedding isn’t over-engineering. It’s where the game is actually won or lost.</p><p>If you want to learn more, see (and star) my project at</p><p><a href="https://github.com/alex1976/Memory-MCP">https://github.com/alex1976/Memory-MCP</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=82f05dde2e5b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Database-MCP: giving AI agents access to your SQL Server or PostgreSQL database]]></title>
            <link>https://blog.devgenius.io/database-mcp-giving-ai-agents-access-to-your-sql-server-or-postgresql-database-74f44683404c?source=rss-486a4f96e33f------2</link>
            <guid isPermaLink="false">https://medium.com/p/74f44683404c</guid>
            <category><![CDATA[database]]></category>
            <category><![CDATA[dotnet]]></category>
            <category><![CDATA[mcp-server]]></category>
            <dc:creator><![CDATA[ENTANGO]]></dc:creator>
            <pubDate>Tue, 08 Sep 2026 18:12:00 GMT</pubDate>
            <atom:updated>2026-09-11T06:08:20.318Z</atom:updated>
            <content:encoded><![CDATA[<p><em>How an MCP server exposes a relational database’s schema, tables, and data to a language model — without ever risking a write.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*a8JXhcdKC-0ThMHbSubsFQ.png" /><figcaption>Database MCP</figcaption></figure><h3>The problem</h3><p>Anyone who works with data spends time writing the same queries over and over: “show me the tables,” “what columns does this view have?,” “pull me the 2025 orders as CSV.” These are mechanical tasks, but they require knowing the schema by heart and writing correct SQL for the right dialect (T-SQL or PostgreSQL).</p><p><strong>Database-MCP</strong> is a server that implements the <em>Model Context Protocol</em> (MCP) and lets Claude (or others agents) explore and extract data from a SQL Server (Azure or on-prem) or PostgreSQL database, using natural language. The idea isn’t to hand an LLM the keys to the database: it’s to give it <strong>only</strong> the ability to read.</p><h3>What it does, from the user’s perspective</h3><p>The server exposes eight MCP tools that Claude can call:</p><p>Tool and what it does:</p><p>list_schemas:Lists user schemas (system schemas excluded)</p><p>list_tables:Lists tables, with an approximate row count</p><p>list_views:Lists views</p><p>describe_table:Columns, primary key, foreign keys, indexes for a table</p><p>describe_view:Columns and SQL definition of a view</p><p>query_data:Queries a table/view with structured filters (no raw SQL)</p><p>execute_sql:Runs a raw SELECT (joins, aggregates, CTEs)</p><p>export_data:Runs a SELECT and streams the full result set to a CSV/TXT file</p><p>The typical flow is: <em>orient</em> (list_schemas/list_tables), <em>inspect</em> (describe_table so column names are never guessed), <em>query</em> (query_data for simple cases, execute_sql for joins and aggregations), <em>export</em> (export_data when the full result set needs to land on disk instead of being pasted into the chat).</p><p>This sequence is also encoded in a Claude skill (skill/SKILL.md) that instructs the model never to guess table or column names and to always prefer query_data when it&#39;s expressive enough.</p><h3>Architecture</h3><p>The server is a single .NET console application that speaks MCP over <strong>stdio</strong>: Claude launches the process, and JSON-RPC messages flow over stdin/stdout, while all logging goes to stderr so it never corrupts the protocol stream.</p><pre>Claude  &lt;--stdio(JSON-RPC)--&gt;  DatabaseMcp.dll<br>                                   │<br>                        ModelContextProtocol SDK<br>                         (tool discovery/dispatch)<br>                                   │<br>                    ┌──────────────┴──────────────┐<br>                 Tools/                          Data/<br>          SchemaTools, DataTools          ISchemaService, QueryService<br>                                                   │<br>                                            Security/<br>                                    SqlGuard, SqlIdentifier<br>                                                   │<br>                                   ┌───────────────┴───────────────┐<br>                            SQL Server                        PostgreSQL</pre><p>Key design points:</p><ul><li><strong>One database per instance.</strong> The DB_PROVIDER variable selects the engine (sqlserver, the default, or postgresql). If both database types need to be reachable, two instances of the server are launched, each under its own tool namespace.</li><li><strong>No ORM.</strong> All data access is hand-written, parameterized ADO.NET against the provider-agnostic DbConnection/DbCommand/DbDataReader interfaces. This gives full control over streaming and predictable performance — an explicit project requirement.</li><li><strong>Two implementations of </strong><strong>ISchemaService.</strong> SqlServerSchemaService uses the sys.* system catalog views; PostgreSqlSchemaService uses information_schema wherever the two engines agree (tables, views, columns, keys), falling back to pg_catalog/pg_stat_user_tables only where needed (indexes, row counts). All queries are fixed and parameterized: no user input is ever concatenated into the SQL text.</li><li><strong>Streaming, not buffering.</strong> QueryService + DelimitedWriter execute the SELECT and stream the DbDataReader directly to CSV/TXT — either inline (row-capped) or to a file (uncapped). Extracting millions of rows never holds the entire result set in memory.</li></ul><h3>The safety model: read-only, for real</h3><p>This is the heart of the project. An LLM that generates SQL is powerful but unpredictable, so the server applies defense in depth across several layers:</p><p><strong>1. </strong><strong>SqlGuard — only </strong><strong>SELECT/</strong><strong>WITH.</strong> Any raw SQL passed to execute_sql/export_data is statically validated: comments are stripped, it&#39;s checked to be a single statement (no multiple ;-separated statements), it must start with SELECT or WITH, and it&#39;s checked against a denylist of dangerous keywords covering both engines — INSERT/UPDATE/DELETE/MERGE/DROP/ALTER, but also engine-specific surface like xp_cmdshell, OPENROWSET (SQL Server) or COPY, dblink, pg_read_file (PostgreSQL).</p><p><strong>2. </strong><strong>query_data never sees raw SQL.</strong> It builds a parameterized SELECT from structured arguments (table, columns, filters, ordering, row limit). Identifiers go through SqlIdentifier, which validates and quotes them correctly per engine (square brackets for SQL Server, double quotes for PostgreSQL); filter values are always bound as parameters, never concatenated text — zero injection surface.</p><p><strong>3. Caps on inline results.</strong> execute_sql/query_data return at most DB_HARD_MAX_ROWS rows (default 10,000) to protect the model&#39;s context window, reporting truncated: true if more rows exist. export_data, by contrast, has no cap: it writes everything to a file.</p><p><strong>4. The real backstop is still the database.</strong> The README is explicit about this: application-level protection doesn’t replace a login with SELECT-only permissions on the target database. It&#39;s defense in depth, not the only line of defense.</p><p>One interesting technical detail: string parameters sent to PostgreSQL are marked as NpgsqlDbType.Unknown, because — unlike SQL Server — Postgres doesn&#39;t implicitly cast a text parameter to compare it against a numeric or date column. Without this workaround, a filter on a date column passed as a string would silently fail.</p><h3>Technology stack</h3><ul><li><strong>.NET 10 / C#</strong>, console application</li><li><a href="https://www.nuget.org/packages/ModelContextProtocol"><strong>ModelContextProtocol</strong></a>, the official C# SDK for MCP — stdio transport, tool discovery via [McpServerToolType]/[McpServerTool] attributes</li><li><strong>Microsoft.Data.SqlClient</strong> for SQL Server, <strong>Npgsql</strong> for PostgreSQL</li><li><strong>Microsoft.Extensions.Hosting</strong> for DI, configuration, and logging</li></ul><p>Configuration is entirely environment-variable driven: DB_PROVIDER selects the engine, then SQLSERVER_*/POSTGRES_* (or the generic DB_* equivalents) set host, credentials, timeouts, and limits. For SQL Server, if SQLSERVER_USER/SQLSERVER_PASSWORD are omitted, it falls back to Windows Integrated Security — convenient for on-prem AD environments.</p><h3>Why this design matters</h3><p>The general lesson here, one that extends beyond this specific project, is that <strong>giving an LLM access to an external system doesn’t mean giving it a raw channel into that system</strong>. Every layer here — the SQL guard, the parameterized query construction, the cap on inline rows, the file-based streaming for bulk exports — exists to make it impossible (or at least very hard) for an unexpected model generation to produce a real side effect on the database. The model can explore, query, export. It can’t write.</p><p><em>The project is tested with xUnit on the pure-logic parts (guard, quoting, query builder, CSV writer) and with optional integration tests against a real database (which create and drop a temporary table, never touching production data).</em></p><p>See more (and star) at:</p><p><a href="https://github.com/alex1976/Database-mcp">https://github.com/alex1976/Database-mcp</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=74f44683404c" width="1" height="1" alt=""><hr><p><a href="https://blog.devgenius.io/database-mcp-giving-ai-agents-access-to-your-sql-server-or-postgresql-database-74f44683404c">Database-MCP: giving AI agents access to your SQL Server or PostgreSQL database</a> was originally published in <a href="https://blog.devgenius.io/">Dev Genius</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Memory-MCP: Guide to Semantic Search From Embeddings to HNSW and Cosine Similarity]]></title>
            <link>https://medium.com/codex/memory-mcp-guide-to-semantic-search-from-embeddings-to-hnsw-and-cosine-similarity-a663b1a07780?source=rss-486a4f96e33f------2</link>
            <guid isPermaLink="false">https://medium.com/p/a663b1a07780</guid>
            <category><![CDATA[mcp-server]]></category>
            <category><![CDATA[semantic-search]]></category>
            <category><![CDATA[machine-learning]]></category>
            <dc:creator><![CDATA[ENTANGO]]></dc:creator>
            <pubDate>Thu, 27 Aug 2026 11:42:34 GMT</pubDate>
            <atom:updated>2026-08-28T11:22:37.698Z</atom:updated>
            <content:encoded><![CDATA[<p>In the landscape of modern Artificial Intelligence, our ability to make machines understand human language has taken a quantum leap.</p><p>Systems like ChatGPT, modern search engines, and recommendation systems no longer rely on simple keyword matching. Instead, they understand <strong>semantic context</strong>.</p><h3>The Context: Project Memory-MCP</h3><p>The concepts explored in this article are a core part of <strong>Memory-MCP</strong>, an ongoing project I am actively developing. <strong>Memory-MCP</strong> is designed to be a <strong>graph-based memory system</strong> engineered to support various AI agents in retrieving highly meaningful, context-aware information. By combining structured knowledge graphs with vector spaces, it bridges the gap between raw data and cognitive recall.</p><p>But how do computers actually grasp that <em>“The cat jumps onto the bed”</em> and <em>“A feline leaps onto the mattress”</em> express the exact same concept, even though they share almost no words? How does a system like <strong>Memory-MCP</strong> rank what is truly “meaningful”?</p><p>The answer lies in the combination of three key elements: <strong>Embeddings</strong>, <strong>Cosine Similarity</strong>, and <strong>ANN</strong> (Approximate Nearest Neighbors) search algorithms. In this article, we will break down how these technologies work step by step.</p><h3>1. The Starting Point: What Are Embeddings?</h3><p>An <strong>embedding</strong> is the conversion of a real-world object (such as text, images, or audio) into a <strong>fixed-length list of numbers</strong>, known as a <strong>vector</strong>.</p><p>When we pass a sentence into an AI model (like those provided by OpenAI or Hugging Face), the text is mapped into an <strong>abstract, multidimensional space</strong> (often exceeding 1,500 dimensions).</p><ul><li><strong>Semantic Placement:</strong> The model assigns numerical coordinates so that words, phrases, or documents with a similar meaning are placed <strong>geometrically close</strong> to each other.</li><li><strong>The Geometry of Meaning:</strong> The words <em>“king”</em> and <em>“queen”</em> will have very similar vectors, just like <em>“dog”</em> and <em>“puppy”</em>.</li></ul><p>Embeddings essentially turn the nuance and ambiguity of human language into pure linear geometry.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/735/1*_Z_Vvkw7KSEVAa0mjhf7sQ.jpeg" /><figcaption>embeddings representation</figcaption></figure><h3>2. Measuring Meaning: Cosine Similarity</h3><p>Once texts are transformed into numerical vectors, we need a metric to measure how close or far apart they are in that geometric space. The standard technique for this is <strong>cosine similarity</strong>.</p><p>Unlike Euclidean distance (which draws a straight line “as the crow flies” between the tips of two vectors), cosine similarity measures <strong>the size of the angle</strong> formed by two vectors starting from the same origin.</p><p>The mathematical formula normalizes the vectors and calculates their dot product:</p><p>\(\text{Cosine\ Similarity}=\frac{A\cdot B}{\|{}A\|{}\|{}B\|{}}\)</p><p>The result is a pure value, always ranging between <strong>-1 and 1</strong>:</p><ul><li><strong>1 (0° Angle):</strong> The vectors point in the exact same direction. This means <strong>maximum semantic similarity</strong>.</li><li><strong>0 (90° Angle):</strong> The vectors are orthogonal. The concepts are <strong>independent</strong> or unrelated.</li><li><strong>-1 (180° Angle):</strong> The vectors point in opposite directions (opposite concepts).</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/692/1*_Kc3-Jz-MUdzMdDIOZxQ1w.jpeg" /><figcaption>similarity concept</figcaption></figure><p><strong>Why Use Cosine Instead of Euclidean Distance?</strong></p><p>In machine learning applied to text, the length of a vector (magnitude) is heavily influenced by word count. A 10-page article and a two-line tweet about the exact same topic will have vectors of vastly different lengths (making them far apart by Euclidean standards).</p><p>Cosine similarity solves this: because it evaluates only the <strong>direction</strong> and ignores the length, it recognizes that both the article and the tweet are talking about the same thing, returning a score close to 1.</p><h3>3. The Search Infrastructure: The Workflow (RAG)</h3><p>In modern enterprise architectures, such as <strong>RAG</strong> (Retrieval-Augmented Generation) systems, the search process follows four main phases:</p><ol><li><strong>Indexing:</strong> All company documents are converted into vectors using an embedding model and saved into a <em>vector database</em> (e.g., Qdrant, Pinecone, Milvus).</li><li><strong>Query Vectorization:</strong> When a user types a question (e.g., <em>“How do I take care of my puppy?”</em>), the query is transformed into a vector using the <strong>exact same model</strong>.</li><li><strong>Distance Calculation:</strong> The database compares the <em>query vector</em> against the stored <em>document vectors</em>.</li><li><strong>Ranking:</strong> The system returns the text chunks with the highest cosine similarity scores.</li></ol><h3>4. The Scale Challenge: Exact k-NN vs. ANN</h3><p>When a database contains only a few texts, calculating the cosine between the query and all documents takes fractions of a millisecond. But what happens when the vectors scale to millions or billions?</p><p>This is where the engineering trade-off between <strong>mathematical precision</strong> and <strong>computational speed</strong> comes into play.</p><p><strong>Exact k-NN (Exact Nearest Neighbors)</strong></p><p>Exact k-NN performs a sequential linear search (<em>brute-force</em>). It compares the query vector against every single item in the database.</p><ul><li><strong>Accuracy:</strong> <strong>100%</strong>. It mathematically finds the absolute closest vectors.</li><li><strong>Complexity:</strong> O(N). If the data doubles, the computation time doubles. This becomes unsustainable at large scale.</li></ul><p><strong>ANN (Approximate Nearest Neighbors)</strong></p><p>ANN gives up 100% mathematical certainty in exchange for blazing-fast execution speeds. It promises to find results that are <em>extremely close</em> to the true best neighbors in near-instantaneous time (\(O(\log N)\) or O(1)).</p><ul><li><strong>Accuracy:</strong> <strong>95% — 99%</strong> (measured in <em>Recall</em>).</li><li><strong>How does it approximate?</strong> Instead of checking every vector, it organizes the space into pre-computed advanced data structures (indexes), instantly isolating the geometric region where the answer is most likely to be found.</li></ul><p><strong>The 3 Most Common ANN Algorithms</strong></p><p>To optimize search, vector databases organize data using three main approaches:</p><ol><li><strong>Graphs (HNSW — Hierarchical Navigable Small World):</strong> The current state-of-the-art. It creates a multi-layered network where upper layers allow for “big jumps” across the vector space, while lower layers handle local, precise navigation.</li><li><strong>Quantization (IVF-PQ):</strong> Divides the space into clusters. The system only searches within the cluster closest to the query. It also compresses vectors to save RAM.</li><li><strong>Trees (KD-Trees):</strong> Recursively splits the space using hyperplanes. Highly effective, but tends to lose efficiency when the space has too many dimensions (<em>the curse of dimensionality</em>).</li></ol><p>FeatureExact k-NNANN (e.g., HNSW)<strong>Accuracy (Recall)</strong>Maximum (100%)Approximate (95–99%)<strong>Search Time</strong>Slow (scales linearly)Ultra-fast (milliseconds on billions of rows)<strong>Memory Usage</strong>Low / ModerateHigh (graph indexes require significant RAM)<strong>Scalability</strong>PoorExcellent</p><h3>5. Conclusion</h3><p>Building an efficient semantic search system isn’t just about choosing the smartest embedding model; it’s about balancing business needs. If you have a small, niche dataset, <strong>Exact k-NN</strong> will give you total precision at zero index cost. However, if you are designing an enterprise system meant to scale, adopting <strong>ANN indexes like HNSW</strong> within a dedicated vector database becomes an absolute necessity.</p><p>if you want to learn more, see (and star) my project at</p><p><a href="https://github.com/alex1976/Memory-MCP">https://github.com/alex1976/Memory-MCP</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a663b1a07780" width="1" height="1" alt=""><hr><p><a href="https://medium.com/codex/memory-mcp-guide-to-semantic-search-from-embeddings-to-hnsw-and-cosine-similarity-a663b1a07780">Memory-MCP: Guide to Semantic Search From Embeddings to HNSW and Cosine Similarity</a> was originally published in <a href="https://medium.com/codex">CodeX</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Memory-MCP: A shared memory layer for AI Agents that work as a team]]></title>
            <link>https://blog.devgenius.io/memory-mcp-a-shared-memory-layer-for-ai-agents-that-work-as-a-team-f948136592ab?source=rss-486a4f96e33f------2</link>
            <guid isPermaLink="false">https://medium.com/p/f948136592ab</guid>
            <category><![CDATA[dotnet]]></category>
            <category><![CDATA[mcp-server]]></category>
            <category><![CDATA[ai-memory]]></category>
            <dc:creator><![CDATA[ENTANGO]]></dc:creator>
            <pubDate>Thu, 20 Aug 2026 09:55:54 GMT</pubDate>
            <atom:updated>2026-08-20T11:46:37.838Z</atom:updated>
            <content:encoded><![CDATA[<h3>Why I built a remote MCP server that lets multiple agents — and the people working alongside them — read from and write to the same memory, instead of each starting from zero.</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*lHJ-X-pubbdE_wcf" /></figure><h3>The problem nobody likes to admit</h3><p>You ask one agent to research a vendor. It reads the docs, extracts the pricing model, writes a summary — and that knowledge dies with the session. Two days later, a <em>different</em> agent, working on the same project for the same team, has to rediscover it from scratch, because there was never a shared place to put it.</p><p>This isn’t a “context window” problem. It’s a coordination problem. Every agent, every tool, every session tends to keep what it learns to itself. Multiply that across a team running several agents on the same project — a research agent, a coding agent, a support agent — and you get the same facts rediscovered independently, sometimes inconsistently, because nothing connects what one agent knows to what another needs.</p><p>What’s missing isn’t a bigger prompt. It’s a shared layer of memory that any authorized agent — or person — can read from and write to, so knowledge accumulates <em>once</em> and stays available to everyone who’s supposed to see it.</p><p>That’s what <strong>Memory-MCP</strong> is: a remote MCP (Model Context Protocol) server for storing, searching, and forgetting memories, organized into multi-tenant <strong>spaces</strong> and protected by API keys — designed so multiple agents and teammates can genuinely share what they know, without stepping on each other or leaking into contexts they shouldn’t.</p><h3>What it actually is</h3><p>Memory-MCP exposes a small set of MCP tools — search_memory, add_memory, listMemories, listDocuments, getDocument, listSpaces, whoAmI — plus resources, a context prompt, and interactive widgets. Any MCP-capable client can connect over HTTP with an API key: Claude Desktop, an agent built on the Claude Agent SDK, a CI pipeline, MCP Inspector — anything speaking the protocol.</p><p>The unit that makes sharing possible is the <strong>space</strong>: a logical container for a project, a client, or a domain. What makes it a genuine collaboration mechanism rather than just a namespace is how access is granted. An API key isn’t tied to one agent — it’s tied to one <strong>identity</strong> (a person, a service, an automation), with Read or ReadWrite permission on each space it&#39;s allowed to touch, and one space marked as its default. Give three different agents three different keys, all granted ReadWrite on the same acme-project space, and every fact one of them saves is immediately visible to the other two on their very next search_memory call — no export, no sync job, no copy-pasting a summary between chat windows.</p><h3>Memory as a shared surface, not a private notebook</h3><p>A few design choices only make sense once you stop thinking of memory as “one agent’s private cache” and start thinking of it as a surface multiple agents read and write concurrently.</p><p><strong>Atomic facts instead of whoever-wrote-it-last text blobs.</strong> When content is saved through add_memory, an IFactExtractor doesn&#39;t just store the raw paragraph — it decomposes it into atomic, self-contained facts (&quot;Alex left Stripe in March&quot;), each becoming its own memory. That matters a lot more once several contributors are writing into the same space over time: atomic facts are unambiguous to combine, re-rank, and search, in a way that competing free-text paragraphs from different agents are not.</p><p><strong>Relations that reconcile contributions instead of just concatenating them.</strong> If a new fact updates, extends, or derives from an existing one — regardless of <em>which</em> agent originally wrote that existing one — a typed graph edge (Updates / Extends / Derives) is created at save time, and an Updates relation automatically deactivates the memory it supersedes. This is the piece that makes multi-agent writing safe: agent B correcting something agent A wrote yesterday doesn&#39;t produce two contradictory memories sitting side by side — it produces a coherent, superseding chain that search_memory&#39;s relatedMemories surfaces automatically.</p><p><strong>Spaces as a hard boundary, not a soft convention.</strong> Because access is enforced per space at the API key level — not by an agent politely deciding what’s relevant — a support agent scoped to customer-x structurally cannot see or pollute customer-y&#39;s memory, even if both are backed by the same Memory-MCP instance. Sharing within a space is deliberate and total; leakage across spaces isn&#39;t possible by construction.</p><p><strong>category and </strong><strong>keyword as shared vocabulary.</strong> When several contributors write into the same space, category becomes a lightweight shared taxonomy (&quot;pricing&quot;, &quot;incidents&quot;, &quot;decisions&quot;) that any agent can filter on, and keyword/fuzzy search (more on that below) means a teammate searching by hand doesn&#39;t need to remember the exact phrasing another agent used when it saved the fact.</p><p><strong>A context prompt that hands off state cleanly.</strong> The context MCP prompt returns a ready-to-attach message — the active space&#39;s recent profile, plus other recently active spaces — which is as useful for onboarding a <em>new</em> agent into an ongoing shared space as it is for resuming a session: whoever picks up the work next starts from what the group already knows, not from an empty conversation.</p><h3>Under the hood: four layers, one direction</h3><p>Memory-MCP is a .NET 10 / ASP.NET Core project, built as Clean Architecture with dependencies flowing one way — Api → Infrastructure/Application → Domain:</p><pre>Memory-MCP/<br>├── Domain/          # Pure entities: Space, ApiKey, Document, Memory — zero framework dependencies<br>├── Application/     # Use cases: IMemoryService, IEmbeddingProvider, repository interfaces<br>├── Infrastructure/  # EF Core, Postgres, the embedding provider, the fact extractor<br>└── Api/             # ASP.NET Core host: MCP tools/resources/prompts as thin adapters</pre><p>Every tool in Api/Tools does exactly three things: resolve the access context, call an application service, format the output. That separation is what lets the same IMemoryService back search_memory, the MCP resources, the context prompt, and every interactive widget identically — whichever surface an agent or a human happens to be using, the sharing and access-control rules behind it are enforced in exactly one place.</p><p>Persistence is plain PostgreSQL via EF Core. Embeddings are stored as native Postgres real[] arrays, and IEmbeddingProvider is pluggable across OpenAI, Azure OpenAI, or Gemini.</p><h3>Graph memory: reconciling knowledge from many contributors</h3><p>When add_memory saves content, an LLM-backed IFactExtractor splits it into atomic facts and classifies each fact&#39;s relationship to a handful of similar existing memories — regardless of who or what originally wrote them. Each fact becomes its own row; each relation becomes a typed, directed MemoryEdge.</p><p>Traversing that graph — “what’s connected to this memory, up to two hops away” — doesn’t need a dedicated graph database: it’s a WITH RECURSIVE CTE over a plain memory_edges table, bounded by a hop count and a visited-node array to guarantee termination. search_memory attaches each top match&#39;s related memories to the result, so whoever — or whichever agent — searches next gets the reconciled picture, not just the most recent write.</p><p>If no extraction model is configured, none of this breaks: add_memory falls back to saving the whole content as a single flat memory. Graph memory is additive on top of shared storage, not a hard dependency of it.</p><h3>A small, honest case study in tuning: fuzzy keyword search</h3><p>Not every feature came from a grand design session. search_memory&#39;s keyword parameter started as a plain case-insensitive ILIKE &#39;%keyword%&#39; match — fine until a teammate searches for something a different agent phrased slightly differently, or just mistypes it.</p><p>The fix is PostgreSQL’s pg_trgm extension, exposed through EF Core as TrigramsAreWordSimilar / TrigramsWordSimilarity, backed by a GIN trigram index. The interesting part was resisting the instinct to lower the similarity threshold below Postgres&#39;s default of 0.6 to catch more typos. Testing that instinct against real data:</p><pre>word_similarity(&#39;migraiton&#39;, &#39;migration&#39;)  = 0.5    -- a real typo, useful to catch<br>word_similarity(&#39;recieve&#39;,   &#39;receive&#39;)    = 0.375  -- also a real typo<br>word_similarity(&#39;plan&#39;,      &#39;plant&#39;)      = 0.8    -- NOT a typo, false positive<br>word_similarity(&#39;sky&#39;,       &#39;skip&#39;)       = 0.5    -- NOT a typo, false positive</pre><p>Short keywords are inherently noisy under trigram similarity: a 4-letter word only has two or three trigrams, so any partial overlap scores deceptively high. Lowering the threshold to catch recieve/receive would also start matching plan/plant as if they were typos of each other — actively worse for a shared space where multiple people search by hand with their own habits and typos. The default threshold stayed, documented explicitly in the codebase, because in a shared search surface, precision matters as much as recall.</p><h3>Interactive widgets: a shared memory people can see, too</h3><p>For MCP clients that support <a href="https://modelcontextprotocol.io/extensions/apps/overview">MCP Apps</a>, Memory-MCP ships four widgets that render inside the conversation: a searchable space picker, a guided save form, a file upload flow (text, Markdown, CSV, and PDF via PdfPig), and a force-directed graph of a space&#39;s memories and relations. These matter specifically because the memory isn&#39;t private to one agent&#39;s session — a teammate can open the graph widget and <em>see</em> what the team&#39;s agents have collectively learned, correct a fact through the same guided-save form an agent would use, or switch which shared space they&#39;re currently working in. The widgets are thin: each is a small postMessage-based bridge to the same tools and resources any agent calls, so a human and an agent editing the same space go through identical rules.</p><h3>Building real infrastructure under real constraints</h3><p>Worth saying plainly: this was built where Docker Desktop is blocked by company policy and the available Postgres has neither pgvector nor admin rights to install it. The original spec called for pgvector with an HNSW index and a dedicated graph database. Neither was available, so both became deliberate trade-offs instead of blockers: cosine similarity computed in-app over a plain real[] column, a recursive CTE instead of a graph engine, pg_trgm — a contrib extension needing no elevated privileges — instead of anything requiring installation. Every one of these is documented in the codebase as a conscious choice, with a note on what migrating to the &quot;ideal&quot; version would take if the constraint ever lifts.</p><h3>Try it</h3><p>Memory-MCP runs anywhere .NET 10 and Postgres run — locally via dotnet run, in Docker via the provided docker-compose.yml, or deployed to Fly.io (coming soon). Give each agent (or each teammate) its own API key scoped to the spaces it should share, point Claude Desktop or your agent framework at the /mcp endpoint, and the same shared memory shows up identically across every one of them.</p><p>Full setup instructions and the reasoning behind every trade-off mentioned here live in the repo: <a href="https://github.com/alex1976/Memory-MCP">https://github.com/alex1976/Memory-MCP</a>.</p><h3>What’s next</h3><p>The roadmap is explicit about what’s deferred: a real graph database (Neo4j) if a space’s graph outgrows recursive CTEs, a native vector index (Qdrant or pgvector, if it becomes available) as more agents share more history in the same space, and richer document ingestion — Word, image OCR, audio transcription — for the upload widget.</p><p>None of it changes the core bet: the more agents and people work on the same problem, the more valuable it is that what one of them learns doesn’t stay locked in a single conversation.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f948136592ab" width="1" height="1" alt=""><hr><p><a href="https://blog.devgenius.io/memory-mcp-a-shared-memory-layer-for-ai-agents-that-work-as-a-team-f948136592ab">Memory-MCP: A shared memory layer for AI Agents that work as a team</a> was originally published in <a href="https://blog.devgenius.io/">Dev Genius</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[OpenAi prompt optmizer]]></title>
            <link>https://medium.com/@entango/openai-prompt-optmizer-d730d19bf55e?source=rss-486a4f96e33f------2</link>
            <guid isPermaLink="false">https://medium.com/p/d730d19bf55e</guid>
            <category><![CDATA[ai-tools]]></category>
            <category><![CDATA[openai]]></category>
            <dc:creator><![CDATA[ENTANGO]]></dc:creator>
            <pubDate>Sun, 24 Aug 2025 13:35:43 GMT</pubDate>
            <atom:updated>2025-08-24T14:06:40.836Z</atom:updated>
            <content:encoded><![CDATA[<p>OpenAI has made available a useful tool for optimizing prompts.</p><p>link: <a href="https://platform.openai.com/chat/edit?optimize=true">https://platform.openai.com/chat/edit?optimize=true</a></p><p>Prompt optmizer uses the guidelines proposed by OpenAI itself for the gpt 5 model.</p><p>link: <a href="https://cookbook.openai.com/examples/gpt-5/gpt-5_prompting_guide">https://cookbook.openai.com/examples/gpt-5/gpt-5_prompting_guide</a></p><p>💡 <strong>How does it work?</strong><br>1. Choose the model for which you want to optimize the prompt</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*n9XDcHCqM-vGfc_DPETPfg.png" /></figure><p>2. Paste your original prompt</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zApiAN67Lo3Q4dS0cWch_g.png" /></figure><p>3. Click “Optimize”</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*YTP_VTd88Z6nsTtBs7Hk0Q.png" /></figure><p>4. The tool rewrites it, applying the official prompting guidelines for the various models (those published by OpenAI itself)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pxdWhO-WvUFYClvEUc36wg.png" /></figure><p>5. Use the new optimized prompt</p><p>🎯 <strong>Result:</strong><br>- Highlights the steps to follow<br>- Eliminates ambiguity<br>- Clearly defines inputs and outputs<br>- Ability to save “optimized” versions and reuse them</p><p><strong>Conclusion:</strong></p><p>This tool is really very useful to make prompts complete and effective</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d730d19bf55e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Data products: what they are and what they are not]]></title>
            <link>https://medium.com/@entango/data-products-what-they-are-and-what-they-are-not-ff011205cd11?source=rss-486a4f96e33f------2</link>
            <guid isPermaLink="false">https://medium.com/p/ff011205cd11</guid>
            <category><![CDATA[data]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[data-driven]]></category>
            <dc:creator><![CDATA[ENTANGO]]></dc:creator>
            <pubDate>Mon, 30 Dec 2024 09:42:22 GMT</pubDate>
            <atom:updated>2024-12-30T09:46:57.075Z</atom:updated>
            <content:encoded><![CDATA[<h3><strong>Data Products: An Overview</strong></h3><p><strong>Definition:</strong><br>Data products are foundational components in a modern data ecosystem, particularly within a <strong>data mesh</strong> architecture. They are designed to serve <strong>analytical data</strong> effectively, applying the principles and practices of software product development to the data domain. By doing so, data products ensure data is accessible, understandable, trustworthy, and valuable to its users.</p><h3>Key Characteristics of Data Products</h3><p>The following attributes define an effective data product:</p><p><strong>1. Discoverable</strong><br>Users should easily locate and understand the data products available to them. This involves robust metadata, intuitive search, and clear documentation.</p><p><strong>2. Addressable</strong><br>Each data product must have a unique identifier (e.g., a URI or URL), ensuring consistent and reliable access programmatically or manually.</p><p><strong>3. Understandable (Self-Describable)</strong><br>Comprehensive documentation is critical. This includes the data product’s purpose, structure, field-level descriptions, usage instructions, and sample data for easy evaluation.</p><p><strong>4. Trustworthy</strong><br>Trust is built through transparency about the product’s quality, performance, and reliability. This includes publishing Service Level Objectives (SLOs) and adhering to measurable Service Level Indicators (SLIs).</p><p><strong>5. Natively Accessible</strong><br>Data products should be tailored for various consumer needs:</p><ul><li>Managers might need prebuilt reports.</li><li>Data scientists could require SQL-based access.</li><li>Engineers might prefer API-based programmatic access.</li></ul><p><strong>6. Interoperable (Composable)</strong><br>To enable seamless integration with other data products, interoperability is key. This includes supporting standard business keys and common access patterns for joining, filtering, and aggregating data.</p><p><strong>7. Valuable on Its Own</strong><br>A data product must deliver independent value, representing a cohesive concept within its domain without requiring additional context or joins to be useful.</p><p><strong>8. Secure</strong><br>Strong access controls, encryption, and compliance with domain-specific regulations ensure the data product is protected against unauthorized use.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/541/1*wub7PmHl2rOItoIaXDr6JA.png" /></figure><p>Note: to learn more about the topic see Zhamak Dehghani’s book “<em>Data Mesh: Delivering Data-Driven Value at Scale”</em></p><h3>Functional Perspective</h3><p>A data product is not merely a dataset; it is a <strong>packaged, self-contained entity</strong> that:</p><ul><li>Provides <strong>structured</strong>, <strong>semi-structured</strong>, or <strong>unstructured analytical data</strong>.</li><li>Caters to specific user groups and their <strong>data consumption patterns</strong>.</li><li>Embeds necessary <strong>automation and infrastructure</strong> to efficiently achieve its purpose.</li></ul><h3>Business Value of Data Products</h3><p>By aligning with the principles of <strong>modern software development</strong>, data products:</p><ul><li>Decompose large, monolithic data systems into manageable, reusable components.</li><li>Encourage scalability, discoverability, and maintainability.</li><li>Support consistent delivery of meaningful <strong>business insights</strong> and value.</li></ul><p>Data products are the smallest valuable unit of analytical data within a data mesh, facilitating <strong>data-driven decision-making</strong> while prioritizing usability and reliability for diverse user personas.</p><h3>What Data Products Are Not</h3><p>A robust definition of data products requires not only specifying what they are but also clarifying what they aren’t. By doing so, organizations can avoid common pitfalls, ensure focus, and streamline the creation and management of effective data products.</p><h3>Why Clarity Matters</h3><ul><li>A narrower, well-defined scope prevents confusion across teams.</li><li>It enables the development of <strong>reusable blueprints</strong> and “paved paths” that simplify building and managing data products.</li><li>It maintains focus on solving problems specific to analytical data rather than trying to address all data-related challenges simultaneously.</li></ul><h3>Common Misrepresentations and Missing Characteristics</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/730/1*IxDo9Dr0oi2LpKvqgqQf0A.png" /></figure><h3>Key Differentiators</h3><ul><li><strong>Data Products vs. Data-Driven Applications:</strong></li><li><strong>Data Products</strong> are designed for <strong>programmatic access</strong> and <strong>composability</strong>, making them building blocks in a data mesh.</li><li><strong>Data-Driven Applications</strong> are intended for <strong>human interaction</strong> and lack inherent composability.</li><li><strong>Focus on Analytical Data:</strong><br>Data products apply software engineering principles to analytical data to address ownership and quality issues, but they are not the catch-all solution for broader enterprise data challenges.</li></ul><h3>Why Misunderstandings Happen</h3><ul><li><strong>Conflation of Concepts:</strong> Teams sometimes mix up data products with other data artifacts or tools due to the overlap in terminology or functionality.</li><li><strong>Diluted Language and Focus:</strong> Attempting to solve all ownership and quality issues under the banner of data mesh risks diluting the transformative impact of focused data product design.</li></ul><h3>Conclusion</h3><p>By clearly distinguishing what data products are and aren’t, teams can maintain focus, improve clarity, and build scalable, reusable solutions that align with the principles of a data mesh. This ensures data products deliver on their promise of creating composable, high-quality analytical data units that drive business value.</p><p>Credits: <a href="https://martinfowler.com/articles/designing-data-products.html">https://martinfowler.com/articles/designing-data-products.html</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ff011205cd11" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[POWERBI Pills n.5 — How to get the first & last value in a date range]]></title>
            <link>https://medium.com/@entango/powerbi-pills-n-5-how-to-get-the-first-last-value-in-a-date-range-43a1166768d2?source=rss-486a4f96e33f------2</link>
            <guid isPermaLink="false">https://medium.com/p/43a1166768d2</guid>
            <category><![CDATA[business-intelligence]]></category>
            <category><![CDATA[dax]]></category>
            <category><![CDATA[power-bi]]></category>
            <dc:creator><![CDATA[ENTANGO]]></dc:creator>
            <pubDate>Tue, 24 Dec 2024 09:50:29 GMT</pubDate>
            <atom:updated>2024-12-24T09:50:29.547Z</atom:updated>
            <content:encoded><![CDATA[<h3>POWERBI Pills n.5 — How to get the first &amp; last value in a date range</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/700/0*MsrdmsnayEMciqfh.jpeg" /></figure><p>In this short DAX pill we see how to find the first and the last value of a given column within a selected time range.</p><p>the context is that of the analysis of the trend of a cryptocurrency (e.g. BITCOIN) in a predefined time frame (e.g. quarter)</p><p>Let’s create the following calculated measurs:</p><ol><li>“<strong>FirstAdjClose</strong>”</li><li>“<strong>LastAdjClose</strong>”</li></ol><p>where:</p><p><strong>CryptoHistorical </strong>is the table where we have the historical data of a cryptocurrency</p><p><strong>FIRSTDATE </strong>is the function that returns the first date in the current context for the specified date column.</p><p><strong>LASTDATE </strong>is the function that returns the last date in the current context for the specified date column.</p><p>see the link:</p><p><a href="https://learn.microsoft.com/it-it/dax/firstdate-function-dax">https://learn.microsoft.com/it-it/dax/firstdate-function-dax</a></p><p><a href="https://learn.microsoft.com/it-it/dax/lastdate-function-dax">https://learn.microsoft.com/it-it/dax/lastdate-function-dax</a></p><p>the DAX sintax is the following:</p><p><em>FirstAdjClose =</em></p><p><em>VAR FirstDateValue = FIRSTDATE(CryptoHistorical[historical.date])</em></p><p><em>VAR result = CALCULATE(MAX(CryptoHistorical[historical.adjClose]), FILTER(CryptoHistorical, CryptoHistorical[historical.date]=FirstDateValue))</em></p><p><em>RETURN result</em></p><p>**********************************************************************</p><p><em>LastAdjClose =</em></p><p><em>VAR LastDateValue = LASTDATE(CryptoHistorical[historical.date])</em></p><p><em>VAR result = CALCULATE(MAX(CryptoHistorical[historical.adjClose]), FILTER(CryptoHistorical, CryptoHistorical[historical.date]=LastDateValue))</em></p><p><em>RETURN result</em></p><p>**********************************************************************</p><p>Note that the date (first or last) is stored in a variable and then passed as a filter to the CALCULATE function</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZTp1Vtp_M42JODD9cw01mA.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=43a1166768d2" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[API economy : pills n.1 — A very useful collection of weather API]]></title>
            <link>https://blog.devgenius.io/api-economy-pills-n-1-a-very-useful-collection-of-weather-api-819c3999555a?source=rss-486a4f96e33f------2</link>
            <guid isPermaLink="false">https://medium.com/p/819c3999555a</guid>
            <category><![CDATA[api-development]]></category>
            <category><![CDATA[data]]></category>
            <category><![CDATA[open-data]]></category>
            <category><![CDATA[api]]></category>
            <dc:creator><![CDATA[ENTANGO]]></dc:creator>
            <pubDate>Thu, 21 Sep 2023 09:58:54 GMT</pubDate>
            <atom:updated>2023-09-27T12:35:46.284Z</atom:updated>
            <content:encoded><![CDATA[<p>With this post I will start a new series of pills that will concern the world of APIs.</p><p>Reference to my previous post about Api economy:</p><p>https://blog.devgenius.io/the-apis-economy-c3ecd72061cd</p><p>I will talk about APIs available online and usable for real purposes and applications, I will talk about tools for API development, I will also talk about products (e.g. API marketplace) dedicated to the world of APIs.</p><p>In this first pill we will see a very useful list of APIs and resources (work in progress) relating to the world of weather (current, forecast), air-quality and other data.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*l-92pnhn0eB0_ldc" /></figure><h3>AccuWeather:</h3><p>Weather and forecast data.</p><p>Access takes place via an ApiKey in HTTP mode and there are various free and paid plans for using the APIs</p><p><a href="https://developer.accuweather.com/apis">API Reference</a></p><h3>Weatherstack:</h3><p>Real-Time &amp; Historical World Weather Data API.</p><p>Access takes place via an ApiKey in HTTPS mode and there are various free and paid plans for using the APIs</p><p><a href="https://weatherstack.com/documentation">Weatherstack - Real-Time World Weather REST API</a></p><h3>OpenWeatherMap:</h3><p>Weather forecasts, nowcasts and history data.</p><p>Access takes place via an ApiKey in HTTPS mode and there are various free and paid plans for using the APIs</p><p><a href="https://openweathermap.org/api">Weather API</a></p><h3>WeatherApi:</h3><p>JSON and XML Weather API and Geolocation API</p><p>Access takes place via an ApiKey in HTTP or HTTPS mode and there are various free and paid plans for using the APIs. Support for CORS is present.</p><p><a href="https://www.weatherapi.com/docs/">Weather and Geolocation API - Weather and Geolocation API JSON and XML - WeatherAPI.com</a></p><h3>US Weather API:</h3><p>Data from US National Weather Service.</p><p>All of the information presented via the API is intended to be open data, free to use for any purpose. Access takes place in HTTPS mode.</p><p><a href="https://www.weather.gov/documentation/services-web-api">API Web Service</a></p><h3>WeatherBit:</h3><p>Current, forecasts and alert weather data. Air quality data.</p><p>Access takes place via an ApiKey in HTTP or HTTPS mode and there are various free and paid plans for using the APIs.</p><p><a href="https://www.weatherbit.io/api">API Documentation</a></p><h3>Tomorrow.io:</h3><p>Enterprise-grade Weather API (current, real-time, forecast)</p><p>Access takes place via an ApiKey in HTTPS mode and there are various free and paid plans for using the APIs.</p><p><a href="https://docs.tomorrow.io/reference/welcome">Tomorrow.io APIs</a></p><h3>Stormglass.io:</h3><p>Weather forecasts &amp; historical data from the world’s most trusted meteorological institutions. Include marine weather (wave and wind).</p><p>Access takes place via an ApiKey in HTTPS mode and there are various free and paid plans for using the APIs.</p><p><a href="https://stormglass.io/">stormglass.io Weather API</a></p><h3>M3O Weather:</h3><p>Real time weather forecast.</p><p>Access takes place via an ApiKey in HTTPS mode and there are various free and paid plans for using the APIs.</p><p><a href="https://m3o.com/weather/api">Weather API - Real time weather forecast</a></p><h3>OpenSenseMap:</h3><p>OpenSenseMap is an open sensor data platform that anyone can participate in. Data comes from Personal Weather Stations called “SenseBoxes”. Air-quality, temperature and humidity data are available.</p><p>Access requires token authentication only for some APIs. Access in HTTP mode.</p><p><a href="https://opensensemap.org/">openSenseMap.org</a></p><h3>INGV Earthquake events:</h3><p>Italian open data on earthquakes.</p><p>All of the information presented via the API is intended to be open data, access is free and does not require ApiKey. Access in HTTP mode.</p><p><a href="https://developers.italia.it/it/api/terremoti-opendata.html">INGV Earthquake event</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=819c3999555a" width="1" height="1" alt=""><hr><p><a href="https://blog.devgenius.io/api-economy-pills-n-1-a-very-useful-collection-of-weather-api-819c3999555a">API economy : pills n.1 — A very useful collection of weather API</a> was originally published in <a href="https://blog.devgenius.io/">Dev Genius</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The APIs economy]]></title>
            <link>https://blog.devgenius.io/the-apis-economy-c3ecd72061cd?source=rss-486a4f96e33f------2</link>
            <guid isPermaLink="false">https://medium.com/p/c3ecd72061cd</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[data-driven]]></category>
            <category><![CDATA[api]]></category>
            <category><![CDATA[software-architecture]]></category>
            <dc:creator><![CDATA[ENTANGO]]></dc:creator>
            <pubDate>Mon, 18 Sep 2023 11:44:35 GMT</pubDate>
            <atom:updated>2023-09-19T11:42:32.617Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*GMaCeB8VdxhrRaj9.png" /></figure><h3>What is an API:</h3><p>An API (Application Programming Interface) is a tool that allows companies to make the data and functionality of their applications available to external developers, business partners and internal departments of the company itself. This allows different services and products to communicate with each other and leverage each other’s information and functionality via a well-documented interface. Developers don’t need to know the technical details of how the API was created; they simply use the interface to interact with other products and services. The use of APIs has grown significantly over the last decade, so much so that many of the most popular web applications today could not exist without the use of APIs.</p><h3>How the API works:</h3><p>An API (Application Programming Interface) is a set of clearly defined rules that dictate how computers or applications should communicate with each other. APIs serve as an intermediary layer situated between an application and a web server, facilitating the processing of data exchange between different systems.</p><p>Here’s how an API works:</p><p>1. A client application initiates an API call, often referred to as a request, to obtain specific information. This request is transmitted from the client application to the web server using the API’s Uniform Resource Identifier (URI). It typically includes a request verb, headers, and sometimes a request body.</p><p>2. Once a valid request is received, the API acts as an intermediary and makes a call to the external program or web server that holds the requested data or functionality.</p><p>3. The server processes the request and sends a response back to the API, containing the requested information.</p><p>4. The API then passes this data back to the initial requesting client application.</p><p>This request and response process takes place entirely through the API. While user interfaces are designed for human interaction, APIs are specifically designed for computer or application-to-application communication.</p><p>APIs are designed with security in mind. Their intermediate position helps simplify the abstraction of functionality between two systems, with the API endpoint acting as a separation layer between the requesting application and the underlying infrastructure providing the service. Here are some key aspects of API security:</p><p>1. <strong>Authorization Credentials</strong>: API calls typically include authorization credentials, such as API keys or tokens. These credentials help verify the identity of the requesting application and reduce the risk of unauthorized access to the server.</p><p>2. <strong>API Gateway</strong>: An API gateway can be used to manage and secure API access. It serves as a central entry point for API requests and can enforce security policies, throttle requests, and provide logging and monitoring to minimize security threats.</p><p>3. <strong>HTTP Headers, Cookies, and Query Parameters</strong>: During the data exchange between the client and server via the API, HTTP headers, cookies, and query string parameters can be used to add additional layers of security. For example, secure cookies can help maintain session state, and headers can be used to specify content types and enforce security policies.</p><p>4. <strong>Rate Limiting</strong>: API security often includes rate limiting to prevent abuse. By restricting the number of requests a client can make within a specific time frame, it helps protect the server from potential denial-of-service attacks.</p><p>5. <strong>Encryption</strong>: To secure data in transit, APIs commonly use encryption protocols such as HTTPS (HTTP Secure) to encrypt the communication between the client and server, ensuring that data remains confidential and cannot be easily intercepted.</p><p>6. <strong>Authentication</strong>: APIs can implement various authentication methods, such as OAuth, API keys, or token-based authentication, to verify the identity of clients and grant access only to authorized users or applications.</p><p>7. <strong>Access Control</strong>: Access control mechanisms within APIs ensure that users or applications can only access the data and functionality they are authorized to use. This helps prevent unauthorized access to sensitive information.</p><p>In summary, APIs incorporate multiple layers of security measures, including authentication, authorization, encryption, and access control, to protect both the API provider’s data and the users of the API. These security features are essential for ensuring the integrity and confidentiality of data exchanged through APIs.</p><p>For instance, let’s take the case of an API provided by a payment processing service. In an e-commerce store application, customers input their card details into the frontend. Instead of needing access to the user’s bank account directly, the payment processor’s API generates a unique token for that specific transaction and includes it in the API request sent to the server. This approach enhances security by reducing the risk of potential hacking threats because the actual card details are not exposed during the transaction.</p><h3>Why we need APIs:</h3><p>Using APIs offers numerous advantages for both managing existing tools and designing new ones. Some of the key benefits of APIs include:</p><p>1. <strong>Improving Collaboration</strong>: Many companies use a wide range of cloud applications, often not integrated with each other. APIs enable integration, allowing these platforms to communicate seamlessly. This integration automates workflows and improves workplace collaboration. Without APIs, companies would be forced to use siled data, compromising productivity and performance.</p><p>2. <strong>Simple Innovation</strong>: APIs offer flexibility, allowing companies to establish connections with new business partners, offer new services to their existing market and enter new markets. For example, Stripe started as an API with a few lines of code and has grown into a billion-dollar company through partnerships with large companies and diversification of services.</p><p>3. <strong>Data Monetization</strong>: Many companies start by offering APIs for free to build a developer base and establish relationships with potential partners. However, if the API offers access to valuable data, you can monetize it by selling access. AccuWeather, for example, has attracted thousands of developers and created a growing community by selling API keys.</p><p>4. <strong>Added Security</strong>: APIs add an extra layer of security between the data and the server. Developers can further enhance API security using tokens, digital signatures, and Transport Layer Security (TLS) encryption. Using API gateways to manage and authenticate traffic helps further protect resources. Additionally, effective API management is critical to ensuring secure operations.</p><p>In summary, APIs are essential tools that facilitate collaboration, foster innovation, enable data monetization, and strengthen the security of business applications and services. They are a key element in digital transformation and the creation of new business opportunities.</p><h3>Types of API protocols:</h3><p>As the use of Web APIs has increased, various protocols have been developed to provide users with a set of well-defined rules that specify the commands and data types accepted. These API protocols simplify the standardized exchange of information. Here are some of them:</p><p>1. <strong>SOAP (Simple Object Access Protocol)</strong>: This is an XML-based API protocol that allows users to send and receive data via protocols such as SMTP and HTTP. SOAP APIs make it easy to exchange information between applications or software components running in different environments or written in different programming languages. It is known for its robustness and support for complex operations.</p><p>2. <strong>XML-RPC</strong>: This protocol uses the XML format for data transfer, but unlike SOAP, it uses a simpler XML format. XML-RPC is older than SOAP but is known for its lightweight and minimal bandwidth usage.</p><p>3. <strong>JSON-RPC</strong>: Similar to XML-RPC, but uses JSON (JavaScript Object Notation) format for data transfer. Both protocols are known for their simplicity and support remote procedure calls (RPCs) with parameters and results.</p><p>4. <strong>REST (Representational State Transfer)</strong>: This is a principle-based Web API architecture rather than a specific protocol. REST APIs (known as RESTful APIs) must respect certain architectural constraints, such as the use of URIs (Uniform Resource Identifier) ​​to identify resources and the use of HTTP methods (GET, POST, PUT, DELETE) to interact with them . There is no official standard for RESTful APIs, but they follow a set of key API design principles.</p><p>It’s important to note that while it’s possible to build RESTful APIs using protocols like SOAP, the two approaches are often thought of as competing specifications and follow different design philosophies. The choice of protocol often depends on the specific needs of the project and the preferences of the development team.</p><h3><strong>Common API examples:</strong></h3><p>APIs have become a valuable asset in the modern business world as they allow companies to offer access to their resources while maintaining security and control. Below are some popular examples of APIs you may encounter:</p><p>1. <strong>Universal Logins</strong>: Many platforms allow users to log in to websites using the login details of their accounts on services such as Facebook, Twitter or Google. This is made possible through APIs, which allow websites to use the authentication credentials of these services to simplify the login process. This saves users the hassle of having to create new accounts for every web service they use.</p><p>2. <strong>Third Party Payment Processing</strong>: Services like “Pay with PayPal” on e-commerce websites use APIs to allow users to make payments securely without having to share sensitive financial information with the website. Payment APIs enable secure and convenient transactions.</p><p>3. <strong>Travel Booking Comparisons</strong>: Travel booking websites aggregate information on flights, hotels and other travel options from multiple sources. This is possible thanks to APIs that provide application users access to a wide range of data updated in real time. Users can easily compare travel options without having to manually consult different sources.</p><p>4. <strong>Google Maps</strong>: Google Maps offers a set of APIs that allow developers to integrate interactive maps and geolocation services into their applications. These APIs allow users to view maps, get directions, find places of interest, and much more. Google Maps APIs are widely used in web and mobile applications.</p><p>5. <strong>Twitter</strong>: Twitter offers an API that allows developers to access tweet data and interact with the platform. This allows developers to create applications and services that use public tweets and replies. For example, social media management applications use the Twitter API to publish tweets and analyze social media activity.</p><p>In summary, APIs are critical to building modern services and applications that rely on data and functionality provided by third parties. They enable integration, security and simplified access to a wide range of digital assets, improving the user experience and expanding business opportunities.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c3ecd72061cd" width="1" height="1" alt=""><hr><p><a href="https://blog.devgenius.io/the-apis-economy-c3ecd72061cd">The APIs economy</a> was originally published in <a href="https://blog.devgenius.io/">Dev Genius</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>